これは何?
- docker container コマンドについて書いたメモです。
- 操作対象が明確になるよう
container
は省略しない。 - 例えば
docker container run
はdocker run
でもよい。 - 各コマンド毎に、Docker公式のドキュメント(英語)、及び Docker-docs-ja(日本語) へのリンクも付けておきます。
- 操作対象が明確になるよう
- 気になった部分は、
[補足]
として詳しく書きました。 - なお、環境は Vagrant Ubuntu18.04(ubuntu/bionic64)、Docker version 18.06.1-ce, build e68fc7a を使用しました。
要約
- コンテナのライフサイクル
- docker container コマンドフロー
- docker container run IMAGE
- docker container attach CONTAINER
- docker container exec CONTAINER
- docker container logs CONTAINER
- docker container stop CONTAINER
- docker container kill CONTAINER
- docker container rm CONTAINER
- docker container start CONTAINER
- docker container pause CONTAINER
- docker container unpause CONTAINER
- docker container prune
- docker container ls
- docker container top CONTAINER
- docker container stats
コンテナのライフサイクル
- 主なものに「
実行中
->停止
->破棄
」がある。 -
実行中
- 指定されたイメージをもとにコンテナが作成され、DockerfileのCMDやENTRYPOINTで定義されているアプリが実行される。
- ここで起動されたアプリが実行中なら、コンテナの状態としても
実行中
となる。
-
停止
- Webアプリなど、HTTPリクエストを受けるコンテナは、
実行中
の状態が継続するので、起動している限り勝手に停止
にはならない。 - コマンドラインツールなど、一度の実行で終了し
停止
になる。
- Webアプリなど、HTTPリクエストを受けるコンテナは、
-
破棄
-
停止
してもコンテナの内部データは保持されており、勝手に破棄
はされない。 - 従って、頻繁にコンテナの開始、停止を繰り返すと、ディスクをどんどん消費するので注意
- なお、コンテナ開始時に
--rm
オプションを付けておけば、停止
と同時に破棄
することも可能
-
docker container コマンドフロー
docker container run IMAGE
- Docker ドキュメント
# 指定イメージからコンテナを生成実行&
# 指定コマンド(/bin/bash)を実行(CMDの上書き実行)
# 指定コマンド終了と伴にコンテナを自動的に破棄(--rm)
$ docker container run -it --rm --name ubuntu ubuntu /bin/bash
# バックグラウンドで起動
$ docker container run -d -p 8080:80 nginx
# ホストの9000を、コンテナの8080へポートフォワードする。
# `curl http://localhost:9000/` で コンテナの8080へつながる。
$ docker container run -d -p 9000:8080 --name echo example/echo:latest`
-
-d
(--detach) : バックグラウンドで実行 -
-t
(--tty) : ホストのシェルの入出力を実行するコンテナの PID=1 につなぐ -
-i
(--interactive) : ホストの入力をコンテナにつなぎ続ける-
ctrl+p
ctrl+q
: コンテナ終了せずホストに戻る - 再度コンテナにつなぐ場合、
docker container attach
する。
-
-
--rm
: コンテナが停止したときに、自動でコンテナを削除する -
--name
: 任意のコンテナ名を付ける(これが無いと適当な名前が付けられる)
[補足] コンテナは停止しても、削除はされません。
- 通常、コンテナが正常であれ異常であれ停止(exited)しても、コンテナは自動で削除されない。
- コンテナを削除するときは、明示的に
docker container rm
またはdocker container prune
コマンドを実行しないと、削除されることはない。 - ただし、自動削除したい場合、
docker container run
で--rm
を付与すれば、コンテナ停止(exited)と同時に削除することもできる。
docker container attach CONTAINER
-
Docker ドキュメント
再度、ホストのシェルの入出力をコンテナにつなぐ(PID=1 につなぐ)
-
PID=1 が
bash
であってもdocker container exec
で新たなbash
の起動がおすすめ- 理由)PID=1 の
bash
でctrl+d
やexit
でシェルを抜けると、コンテナ自身が終了してしまう為
- 理由)PID=1 の
docker container exec CONTAINER
- Docker ドキュメント
$ docker container exec -it ubuntu /bin/bash # コンテナ内で新しいbashを起動する。
$ docker container exec ubuntu ls -al /
- running コンテナ内で任意のコマンドを実行する。
- PIDは新たに採番される(つまり、
docker container attach
のように PID=1 にはつながらない) -
-it
: ホストのシェルの入出力を実行するコマンドにつなぐ-
ctrl+p
ctrl+q
: 実行コマンドを終了せずホストに戻る
-
docker container logs CONTAINER
-
Docker ドキュメント
コンテナのログを表示する。
コンテナの PID=1 の標準出力(エラー出力も)が logs になるので、例えば PID=1 が
bash
の場合、ここで操作した内容も、logs コマンドから見ることが出来る。-f
(--follow) : 出力を追いかける(出力を待ち続ける)
docker container stop CONTAINER
-
Docker ドキュメント
コンテナを停止させる。(running -> exited)
-
デフォルトでは、コンテナの PID=1 へ SIGTERM を送信し停止させる。ただし、10秒経っても停止しない場合、SIGKILL を送信し強制終了になる。
- つまり、すぐに停止しない場合、強制終了になった可能性が高いので要注意
[補足] docker container stop
ですぐに停止しない理由
-
コンテナが停止するまで。
- 1)
docker container stop
は 、コンテナ内の PID=1 に SIGTERM を送信する。 - 2) SIGTERM を受けた PID=1 のプロセスが終了処理を行い停止する。
- 1)
ところが、PID=1 で実行されたプロセスは特殊で、デフォルトで全てのシグナルを無視する。
-
Docker run リファレンス — Docker-docs-ja 17.06.Beta ドキュメント
http://docs.docker.jp/engine/reference/run.htmlコンテナ内で PID 1 として実行しているプロセスは、Linux が特別に扱います。
デフォルトの操作では、あらゆるシグナルを無視します。
そのため、プロセスは SIGINT か SIGTERM で停止するようにコードを書かない限り、停止できません。 つまり、SIGINT、SIGTERM を適切に処理するコードを書いたプログラムを PID=1 で実行させないと
docker container stop
してもすぐには停止しない。--init
で解決するようだ。おそらく表面上は・・・
[補足] --init
について
- 恐らく『コンテナがすぐに停止しない問題を、安易に --init で解決してしまう』と、実害として『kubernetes などで、オートスケーリングの都度、正体不明のアプリ不具合が生じる可能性』がある。
- なぜなら、
--init
はシグナルを受信できるプロセスを PID=1 で動かすだけで、これの子として実行するアプリレベルで見れば、適切な終了になっている保証は無い。 - 本来なら、アプリに応じた適切な終了処理をシグナル受信時に行うべき。行っていない場合、シグナルを受けると即終了してしまう為、負荷の急増/急減で大量のコンテナが停止すると、まさに処理中(通信中、ファイルアクセス中など)にシグナル受信し、強制終了するケースが頻発するはず。
docker container kill CONTAINER
-
Docker ドキュメント
普通は使わない。
コンテナを強制停止させる。(running -> exited)
デフォルトで SIGKILL を送信する。
-
docker container stop
を使うべき- 理由)SIGTERM を送信することで、アプリの適切な終了処理を促せる。(終了処理があるならですが)
docker container rm CONTAINER
- Docker ドキュメント
# 指定イメージで起動されたコンテナを全て強制削除
$ docker container rm -f $(docker container list --filter "ancestor=<イメージ名>" -q)`
- コンテナを削除する。
- 誤って削除しても二度と復活しないので注意
- 操作を誤って running コンテナ を削除しようとしても、できない安心設計になっている。
- '-f'(--force) : running コンテナも強制削除したいとき
docker container start CONTAINER
-
Docker ドキュメント
コンテナを開始する。exited を 再度 running へ
docker container pause CONTAINER
-
Docker ドキュメント
コンテナを一時停止する。running を paused へ
docker container unpause CONTAINER
-
Docker ドキュメント
コンテナの一時停止を解除する。paused を running へ
docker container prune
-
Docker ドキュメント
-
停止中(exited)のコンテナを完全に削除する。
- 誤って削除しても二度と復活しないので注意
1コンテナ毎に
docker container rm
する手間を省ける。
docker container ls
- Docker ドキュメント
$ docker container ls
# コンテナの状態でフィルタ status=(created|restarting|removing|running|paused|exited)
$ docker container ls -a --filter 'status=running'
# コンテナ名でフィルタ name=<コンテナ名>
$ docker container ls -a --filter 'name=ubuntu'
- コンテナの一覧を表示する。
-
ls
はlist
ps
でもいい -
-a
(--all) : 全状態のコンテナの一覧(default runningコンテナのみ) -
-f
(--filter) : フィルタ条件
$ man docker-container-ls
:
Filter output based on these conditions:
- ancestor=(<image-name>[:tag]|<image-id>| ⟨image@digest⟩)
containers created from an image or a descendant.
- before=(<container-name>|<container-id>)
- expose=(<port>[/<proto>]|<startport-endport>/[<proto>])
- exited=<int> an exit code of <int>
- health=(starting|healthy|unhealthy|none)
- id=<ID> a container's ID
- isolation=(default|process|hyperv) (Windows daemon only)
- is-task=(true|false)
- label=<key> or label=<key>=<value>
- name=<string> a container's name
- network=(<network-id>|<network-name>)
- publish=(<port>[/<proto>]|<startport-endport>/[<proto>])
- since=(<container-name>|<container-id>)
- status=(created|restarting|removing|running|paused|exited)
- volume=(<volume name>|<mount point destination>)
[補足] コンテナの状態(created|restarting|removing|running|paused|exited)を取得する方法は?
コンテナの状態には、(created|restarting|removing|running|paused|exited) があるらしいが、
docker container ls
で表示されるSTATUS
(ex. "Up 25 minutes") は加工されているので、加工されていないものが見たい。docker container ls
の--format
でやってみる → 失敗
$ FMT="table {{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}\t{{.Status}}\t{{.Size}}\t{{.CreatedAt}}\t{{.RunningFor}}\t{{.Ports}}\t{{.Networks}}\t{{.Labels}}"
$ docker container ls -a --format "$FMT"
CONTAINER ID IMAGE NAMES COMMAND STATUS SIZE CREATED AT CREATED PORTS NETWORKS LABELS
1816cfc302a8 nginx tender_nobel "nginx -g 'daemon of…" Up About a minute 2B (virtual 109MB) 2018-09-09 17:55:17 +0900 JST 3 minutes ago 0.0.0.0:8080->80/tcp bridge maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>
e234e67b68d0 ubuntu boring_stonebraker "--name ubuntu" Created 0B (virtual 84.1MB) 2018-09-09 17:26:02 +0900 JST 33 minutes ago bridge
- Docker API でやってみる → 成功
$ # API経由で全コンテナのリストを得る
$ curl -s --unix-socket /var/run/docker.sock http:/v1.37/containers/json?all=true \
| python3 -mjson.tool \
| head -25
[
{
"Id": "1816cfc302a8149a94cb60eb13bf0570262ac61ca951deb898835440fe517597",
"Names": [
"/tender_nobel"
],
"Image": "nginx",
"ImageID": "sha256:06144b2878448774e55577ae7d66b5f43a87c2e44322b3884e4e6c70d070b262",
"Command": "nginx -g 'daemon off;'",
"Created": 1536483317,
"Ports": [
{
"IP": "0.0.0.0",
"PrivatePort": 80,
"PublicPort": 8080,
"Type": "tcp"
}
],
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"State": "running", # <------------------------- 状態
"Status": "Up 3 minutes",
"HostConfig": {
"NetworkMode": "default"
$
$ # jqを使って、コンテナ名と状態のみ抽出
$ curl -s --unix-socket /var/run/docker.sock http:/v1.37/containers/json?all=true \
| jq -r '[ .[] | { Name: .Names[0], State: .State } ]' \
| jq -r '["Name","State"], (.[] | [.Name,.State]) | @csv' \
| column -t -s ,
"Name" "State"
"/tender_nobel" "running"
"/boring_stonebraker" "created"
"/ubuntu" "exited"
docker container top CONTAINER
-
Docker ドキュメント
コンテナ内のプロセス一覧を表示
コンテナ内部で ps するのと同じイメージ
[補足] コンテナ内部で実行したプロセスがどのように見えるか?
ubuntuコンテナ内部で、sleep を2つをバックグラウンドで動かして、
docker container top
や 普通にps
してみる。まず、コンテナから
$ # コンテナを起動し、コンテナ内部で、sleep を動かしておく
$ docker container run -it --name ubuntu ubuntu /bin/bash
root@fc659b390b7f:/# sleep 1000000 &
[1] 10
root@fc659b390b7f:/# sleep 1000000 &
[2] 11
root@fc659b390b7f:/# ps -alxf
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
4 0 1 0 20 0 18508 3448 wait Ss pts/0 0:00 /bin/bash
4 0 10 1 20 0 4532 780 hrtime S pts/0 0:00 sleep 1000000
0 0 11 1 20 0 4532 776 hrtime S pts/0 0:00 sleep 1000000
4 0 12 1 20 0 25944 1412 - R+ pts/0 0:00 ps -alxf
root@fc659b390b7f:/# read escape sequence ---- ### ctrl+p ctrl+q でコンテナを抜けホストに戻る
- 次に、ホストから
$ # docker container top してみる → コンテナから見たPID、PPIDとは違って見えている(プロセス空間が隔離されている為)
$ docker container top ubuntu
UID PID PPID C STIME TTY TIME CMD
root 20808 20775 0 01:10 pts/0 00:00:00 /bin/bash
root 21200 20808 0 01:16 pts/0 00:00:00 sleep 1000000
root 21203 20808 0 01:16 pts/0 00:00:00 sleep 1000000
$
$ # docker container top で、オプション指定して、詳細を見る
$ docker container top ubuntu -alxf
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
4 0 20808 20775 20 0 18508 3444 poll_s Ss+ pts/0 0:00 | \_ /bin/bash
4 0 21200 20808 20 0 4532 780 hrtime S pts/0 0:00 | \_ sleep 1000000
0 0 21203 20808 20 0 4532 776 hrtime S pts/0 0:00 | \_ sleep 1000000
$
$ # ホストで普通に ps してみる → コンテナ内部のプロセスも見えている(コンテナはホストのkernelを使っている為)
$ ps -alxf
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
:
4 0 1286 1 20 0 1113408 54580 - Ssl ? 10:40 /usr/bin/dockerd -H fd://
4 0 1435 1286 20 0 1024084 23248 - Ssl ? 8:22 \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
4 0 20775 1435 20 0 8908 4412 - Sl ? 0:00 \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/fc659b390b7f525d6be7e69d0f2610887fffc05f75
4 0 20808 20775 20 0 18508 3444 - Ss+ pts/0 0:00 \_ /bin/bash
4 0 21200 20808 20 0 4532 780 - S pts/0 0:00 \_ sleep 1000000
0 0 21203 20808 20 0 4532 776 - S pts/0 0:00 \_ sleep 1000000
$
docker container stats
- top コマンドのようなもの
$ docker container stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c4fd37367595 echo 0.00% 6.887MiB / 1.947GiB 0.35% 6.71kB / 890B 149MB / 0B 14