docker コマンドとその用途についてまとめ

## このページについて

docker image を作るにあたって、そもそも叩いてるコマンドの用途をしっかり理解していなかったので調べてまとめました  
docker や docker-compose 使えるけどコンテナとかイメージがどういうことになっているかまでは理解してない人には価値があるのではないでしょうか(2019-10)

## 前提

```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G65

$ docker -v
Docker version 19.03.2, build 6a30dfc
```

## 内容

知りたいのはコンテナを立ち上げ(start)たり、ビルドしたらコンテナはどういう状態になるかということ。
その辺に関係ありそうなコマンドと動きを調べてみる

## そもそもコンテナやイメージについて

イメージは自身を構成するのに必要な読み込みのみのレイヤ(Dockerfileに記述された実行手順毎の集まり)でできている。例えば、 `RUN mkdir /hoge` で一つのレイヤ(ファイル)が出来上がる。
ちなみにイメージを構成しているレイヤは下記コマンドで見れる

ex.) golang imageの例

```
$ docker history golang
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
dc7582e06f8e        8 days ago          /bin/sh -c #(nop) WORKDIR /go                   0B                  
<missing>           8 days ago          /bin/sh -c mkdir -p "$GOPATH/src" "$GOPATH/b…   0B                  
<missing>           8 days ago          /bin/sh -c #(nop)  ENV PATH=/go/bin:/usr/loc…   0B                  
<missing>           8 days ago          /bin/sh -c #(nop)  ENV GOPATH=/go               0B                  
<missing>           8 days ago          /bin/sh -c set -eux;   dpkgArch="$(dpkg --pr…   327MB               
<missing>           8 days ago          /bin/sh -c #(nop)  ENV GOLANG_VERSION=1.13.3    0B                  
<missing>           9 days ago          /bin/sh -c apt-get update && apt-get install…   182MB               
<missing>           9 days ago          /bin/sh -c apt-get update && apt-get install…   145MB               
<missing>           9 days ago          /bin/sh -c set -ex;  if ! command -v gpg > /…   17.5MB              
<missing>           9 days ago          /bin/sh -c apt-get update && apt-get install…   16.5MB              
<missing>           10 days ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B                  
<missing>           10 days ago         /bin/sh -c #(nop) ADD file:9e9de089953800c4e…   114MB 
```

レイヤにはIDが振られている

```
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
dc7582e06f8e        8 days ago          /bin/sh -c #(nop) WORKDIR /go                   0B
```

イメージは読み込みのみなので、他のイメージを作るときにキャッシュがあれば使えるし、そのイメージの上にレイヤを重ねて新たなイメージにすることもできる。これはみんな無意識に使っていることだろう。もし、この機能がなければ、コンテナを実行するたびに新たにイメージが必要になり、長い起動時間や大きなディスク容量を必要としてしまう。この仕組みは **ユニオンファイルシステム** というらしい。

そして、出来上がったイメージを run させるとイメージレイヤの一番上に読み書き可能なレイヤが追加され(create)、コンテナが実行状態になる(start)。start時にプロセスになる模様。
docker run は裏で docker create と　docker start を呼んでいる。
このような遷移のため、 `docker run -v <マウント先>` としてしたときのホストとの関連は読み書き可能なレイヤの上で行われているのだろう。ただし、ホストとのマウントはコンテナ容量と線形なので、docker volume を使ったほうがいいらしい([参考](https://docs.docker.com/storage/volumes/))。docker がマネージするストレージでコンテナのサイズを増加させない、外部ディスクのような働きをする模様。docker volume で作ったストレージにマウントするときは `-v` ではなく、 `--mount` を使うのを推奨していた。

## 結論

docker build はイメージ作るためにレイヤを積み重ねる作業をする。  
docker run はイメージの上に読み書き可能なレイヤをのっけて、さらにプロセスとして起動状態にする

docker stop は起動状態のコンテナを停止する。停止するだけで、コンテナとしては生き残っている。
コンテナの読み書きレイヤの削除は `docker rm <container-id>` を使う(コンテナ停止の必要あり)。ホストやdocker volumeの別の場所とマウントしたいときに使う感じかな？自分は意識して使ったことがない。イメージを削除するには `docker rmi <image-id>` を使う。 -f を使うと中間レイヤまで削除することが可能。

### 実験

```
$ tree
.
└── src
    └── hello.txt

1 directory, 1 file
```

```bash
$ docker run -v $(pwd):/tmp -i -t -d ubuntu:18.04 /bin/bash
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                                                                NAMES
dfe1164925e4        ubuntu:18.04        "/bin/bash"              7 minutes ago       Up 7 minutes                                                                                   nervous_tesla
$ docker stop dfe1164925e4
$ docker rm dfe1164925e4
# すぐに起動できる
# 当然だがコンテナ内のtmpにマウントしていたものはなくなっている
$ docker run -i -t -d ubuntu:18.04 /bin/bash
c3d4b6a590ee440dbb61bef73873f78eaa267ce55442387f05d04bd9dcc94a0c
```



## 参考

- https://www.docker.com/resources/what-container
- https://medium.com/@jessgreb01/digging-into-docker-layers-c22f948ed612#targetText=What%20are%20the%20layers%3F,during%20the%20Docker%20image%20build.
- https://www.slideshare.net/zembutsu/docker-images-containers-and-lifecycle
- http://enakai00.hatenablog.com/entry/20140628/1403933390
- https://fa-works.com/blog/visualizing-docker-containers-and-images
- http://docs.docker.jp/engine/userguide/storagedriver/imagesandcontainers.html
- https://docs.docker.com/storage/volumes/