docker back to the basic 

# TL;DR

以下のようなコマンドを使いこなそう

参考) http://docs.docker.jp/engine/reference/commandline/index.html

```
$ docker image ls
$ docker container ls
$ docker container ls -a
$ docker run -id --name hoge --rm -v $(pwd):/home
$ docker container exec
$ docker container attach
$ docker build -t [image-name] .
```

# 基礎知識

- コンテナ型の仮想化では、コンテナはホストOSのカーネルを利用する。

- 1コンテナ1プロセスで使用する。

- Web server container やDB server container など複数のコンテナを立てる。

- コンテナにはそれぞれ仮想NIC(eth0)が割り当てられる。

- コンテナ同士で通信することが可能である。

> NIC(ニック) : 別名 LANカード、Ethernetカード
> NICとは、コンピュータなどの機器を通信ネットワーク（LAN）に接続するためのカード型の拡張装置。筐体背面や側面などに用意された[拡張スロット](http://e-words.jp/w/拡張スロット.html)などに挿入して使用する。単にNICといった場合は最も普及している[イーサネット](http://e-words.jp/w/Ethernet.html)（Ethernet = 有線LANのこと）に接続するためのコネクタ（[RJ45](http://e-words.jp/w/RJ45.html)）のことを指す。(引用 http://e-words.jp)

# What is image and what is container?

docker には、**image**と**container**の２つがある。

OSのインストールDVDを仮想化したものがDockerイメージであり、

OSが起動しているサーバを仮想化したものがコンテナに相当する。

# 基本コマンド

まず、一番簡単なHello Worldをやってみます。

hello-worldというDockerイメージが用意されていますので、`docker run　hello-world`コマンドで起動します。

```bash
$ sudo docker run hello-world
```



**pullしてきたDockerイメージの一覧**は`docker image ls`コマンドで確認できます。

```bash
$ docker image ls
$ docker container ls -a
```

作成済Dockerコンテナの一覧は`docker container ls -a`で確認できます。

"-a"は「コンテナ一覧をすべて表示」するためのオプションです。これをつけないと起動中のコンテナしか表示されません。

dockerイメージの削除コマンドは`docker image rm [Repository]` 
コンテナの削除コマンドは`docker container rm [containerID]`

```bash
$ docker image rm hello-world
$ docker container rm 484810ae0812
```

注意) `docker run`からの状況から脱するには**「ctrlキーを押しながら'pq'と押す」**

# ホスト側との「ディレクトリ共有」

**「ホストOSのディレクトリ」と「コンテナ内の/home/」をつなぐ。**

**「-v」オプション**は、ポートフォワード設定の「-p」オプションと同様、***コロンの左側(/root/tomcat-container/logs)がホスト側、右側(/share/logs)が<u>コンテナ内のディレクトリ</u>を表していて***、そのディレクトリが共有されるかたちとなります。

```bash
$ docker run -it -d --name hogehoge -v $(pwd):/home ubuntu:16.04 bash
```

# docker container exec

`docker container ls -a `でまだコンテナが起動している場合、またコンテナに入ることができるはずである。起動しているコンテナに入る方法は2つある。

- `docker container attach`コマンドを使う方法
- `docker container exec`コマンドを使う方法

**attachは「ゲストOSの標準入力／標準出力を、ホストOSの標準入力／標準出力とつなげる」という意味です。**attachは「既に起動している」1つのプロセスへつなぎに行きます。

```bash
$ docker container attach 5
$ ps aux
# ctrlキー + 'pq'
```

**execは「引数のコマンドを実行する」という意味です。**

execでは現在起動しているbashとは別に、新たにbashを起動します。

```bash
$ docker container exec -it 5 bash
$ ps aux
$ exit
```

# DockerFile の作り方

Docker imageからDocker containerを作成する際に「必要なパッケージのインストール手順や実行コマンドなど」をスクリプト化したもの。

```bash
$ docker build -t workcheck
```



## FROM

`FROM` 命令は、以降の命令で使う [ベース・イメージ](http://docs.docker.jp/glossary.html#base-image) を指定します。あるいは、有効な `Dockerfile` は、１行めを `FROM` 命令で指定する必要があります。イメージとは、あらゆる有効なものが利用できます。 パブリック・リポジトリ から **イメージを取得する** 方法が一番簡単です。

```dockerfile
# ubuntu 14.04のイメージを使う
FROM ubuntu:14.04
```



## MAINTAINER

`MAINTAINER` 命令は、生成するイメージの *Author* （作者）フィールドを指定します。



## RUN 

イメージ作成時に実行するコマンドを書く。

`RUN` 命令は既存イメージ上の新しいレイヤで、あらゆるコマンドを実行し、その結果をコミットする命令です。コミットの結果得られたイメージは、 `Dockerfile` の次のステップで使われます。

```dockerfile
#  update後にapache2をインストール
RUN apt update .
RUN apt install apache2 -y
```



## CMD 

`Dockerfile` で `CMD` 命令を一度だけ指定できます。複数の `CMD` がある場合、最も後ろの `CMD` のみ有効です。

`CMD` の主な目的は、 **コンテナ実行時のデフォルトを提供します** 。 デフォルトには、実行可能なコマンドが含まれているか、あるいは省略されるかもしれません

```dockerfile
# nodeでサーバを起動する
CMD [ "node", "server.js" ]
```



## EXPOSE 

指定のポートを外部に公開する。

`EXPOSE` 命令は、特定のネットワーク・**ポートをコンテナが実行時にリッスンする**ことを Docker に伝えます。 `EXPOSE` があっても、これだけではホストからコンテナにアクセスできるようにしません。アクセスするには、 `-p` フラグを使ってポートの公開範囲を指定するか、 `-P` フラグで全ての露出ポートを公開する必要があります。

```dockerfile
# 80番ポートを外部に公開する
EXPOSE 80
```



## ENV

`ENV` 命令は、環境変数 `` と 値 `` のセットです。値は `Dockerfile` から派生する全てのコマンド環境で利用でき、 [インラインで置き換え](http://docs.docker.jp/engine/reference/builder.html#environment-replacement) も可能です。

`ENV` 命令は２つの形式があります。１つめは、 `ENV ` であり、変数に対して１つの値を設定します。はじめの空白以降の文字列が `` に含まれます。ここには空白もクォートも含まれます。

２つめの形式は `ENV = ...` です。これは一度に複数の変数を指定できます。先ほどと違い、構文の２つめにイコールサイン（=）があるので気を付けてください。コマンドラインの分割、クォート、バックスラッシュは、空白スペースも含めて値になります。

```dockerfile
ENV <key> <value>
ENV <key>=<value> ...
```



## ADD

`ADD` 命令は `<ソース>` にある新しいファイルやディレクトリをコピー、あるいはリモートの URL からコピーします。それから、コンテナ内のファイルシステム上にある `送信先` に指定されたパスに追加します。

複数の `<ソース>` リソースを指定できます。この時、ファイルやディレクトリはソースディレクトリ（構築時のコンテクスト）からの相対パス上に存在しないと構築できません。

それぞれの `<ソース>` にはワイルドカードと Go 言語の [filepath.Match](http://golang.org/pkg/path/filepath#Match) ルールに一致するパターンが使えます。例えば、次のような記述です。

```dockerfile
ADD hom* /mydir/        # "hom" で始まる全てのファイルを追加
ADD hom?.txt /mydir/    # ? は１文字だけ一致します。例： "home.txt"
ADD test relativeDir/          # "test" を `WORKDIR`/relativeDir/ （相対ディレクトリ）に追加
ADD test /absoluteDir/          # "test" を /absoluteDir/ （絶対ディレクトリ）に追加
```



## COPY

`COPY` 命令は `<ソース>` にある新しいファイルやディレクトリをコピーするもので、コンテナ内のファイルシステム上にある `<送信先>` に指定されたパスに追加します。

```dockerfile
COPY hom* /mydir/        # "hom" で始まる全てのファイルを追加
COPY hom?.txt /mydir/    # ? は１文字だけ一致します。例： "home.txt"
```

## 例) Node.jsのアプリケーションを起動する

```dockerfile
FROM node:12

# アプリケーションディレクトリを作成する
WORKDIR /usr/src/app

# アプリケーションの依存関係をインストールする
# ワイルドカードを使用して、package.json と package-lock.json の両方が確実にコピーされるようにします。
# 可能であれば (npm@5+)
COPY package*.json ./

RUN npm install
# 本番用にコードを作成している場合
# RUN npm install --only=production

# アプリケーションのソースをバンドルする
COPY . .

EXPOSE 8080
CMD [ "node", "server.js" ]
```