本題の前に
位置付け・前提
本記事は、社内ワークショップ のために用意したものです。そのため、次の前提で進めることをご理解ください。
また、本稿はこちらの続きとなります。
コンテナ技術 ハンズオン Vol.1 Docker操作編
コンテナ技術 ハンズオン Vol.2 Dockerイメージ編
コンテナ技術 ハンズオン Vol.3 Docker Compose編
目的や前提なども上記の内容に準拠します。
docker ハンズオン環境
今回も Play with Docker を活用してハンズオンを行います。
※要:Docker Hub アカウント
注意点として、この環境は4時間の制限があります。4時間経過すると環境が削除されてしまう点を注意して下さい。
もちろんローカル環境でも構いません。
ハンズオン
今回のゴール
- Docker のリソースを制御できるようになる
- Docker のトラブルシューティングができるようになる
今回やらないこと
- kubernetes などのオーケストレーションツールは使いません。
Docker リソース管理
Docker ネットワーク管理
これまでなんとなくポートの紐付けを設定したりしてきました。実は、Docker 内でネットワークを形成しています。
実は Docker 内でIPアドレスもポート番号も保有しており、TCP/IPネットワークを形成することが可能です。
仕組みとしては、brige / host / none の3パターンです。
brige≒NAPT、host=ホストNIC共有、none=Docker内のクローズドネットワークと覚えると良いでしょう。(ポートフォワードするので、NATというよりNAPT)
どの bridge に接続するかを選択でき、複数接続することも可能です。
ちなみに、これまで Dockerfile/Docker Compose で活用してきた links 指定は、今後廃止されていく可能性があるそうです。
詳しくは下記のドキュメントを読むと良いでしょう。
- Docker container networking | Docker Documentation ※英語
- Docker コンテナ・ネットワークの理解 — Docker-docs-ja 17.06.Beta ドキュメント
- Compose のネットワーク機能 — Docker-docs-ja 17.06.Beta ドキュメント
- network - 入門 Docker
- Docker の基本学習 ~ Docker のネットワーク
- Dockerのネットワーク構成
Docker ネットワーク管理 ハンズオン
まず、現状のDockerネットワークを確認します。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c248babe0bdd bridge bridge local
97c31c8afe7b host host local
e950afaacc2f none null local
前述した3種類のネットワークが出力されます。
ホストではどう認識されているかを確認しましょう。
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:48:44:88:eb brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
40422: eth1@if40423: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.4/16 scope global eth1
valid_lft forever preferred_lft forever
40424: eth0@if40425: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether f2:c8:73:a7:5c:9c brd ff:ff:ff:ff:ff:ff
inet 192.168.0.38/23 scope global eth0
valid_lft forever preferred_lft forever
2 に docker 0 というネットワークがあります。これが docker ネットワークとなります。
レガシーですが、ifconfig の方がキレイに表示されます。
$ ifconfig -a
docker0 Link encap:Ethernet HWaddr 02:42:48:44:88:EB
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
eth0 Link encap:Ethernet HWaddr F2:C8:73:A7:5C:9C
inet addr:192.168.0.38 Bcast:0.0.0.0 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1296 (1.2 KiB) TX bytes:0 (0.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:04
inet addr:172.18.0.4 Bcast:0.0.0.0 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:842 errors:0 dropped:0 overruns:0 frame:0
TX packets:502 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:138667 (135.4 KiB) TX bytes:628366 (613.6 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
この docker0 が仮想L2スイッチ(ブリッジ)、つまり bridge ということになります。VMwareの世界なら仮想スイッチが近いイメージ。
なお、コンテナ/インスタンスには、Dockerが自動でアドレスを割り振るDHCPとなっています。
ちなみに、bridge の詳しい情報は下記で確認できます。
docker network inspect bridge
返り値は JSON 形式で得られます。
[
{
"Name": "bridge",
"Id": "c248babe0bdd29536ee37983ecc7467ad975a85d985523210deb1662f535c3d0",
"Created": "2019-09-01T06:30:44.029906596Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"8f5fdb0b119bad4d9bfb791ceee9d1f0655a7fe9e4706c78fa6bb72c7146fd60": {
"Name": "ngtest",
"EndpointID": "d1a94602f456e2092124f9ec35973481dc21667c38cdd5bef8dc2e548ba52add",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
課題1 |
---|
同じように host および none についても、詳細情報を表示してみましょう。 |
次に、インスタンスをブリッジに繋いでみましょう。
docker run -it -d --name ngtest -p 80:80 nginx
これで ホストの80版ポートに紐付いた Nginx コンテナが起動します。再度ネットワークを確認します。
$ ifconfig -a
(略)
vethb06656b Link encap:Ethernet HWaddr F2:1C:5D:03:21:F5
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3904 (3.8 KiB) TX bytes:3670 (3.5 KiB)
vethXXXXXXX が増えています。これはコンテナの仮想NICです。
次のコマンドだと、docker0 と接続していることが分かります。
$ ip a
(略)
2: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:48:44:88:eb brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: vethb06656b@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 state UP
link/ether f2:1c:5d:03:21:f5 brd ff:ff:ff:ff:ff:ff
40422: eth1@if40423: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.4/16 scope global eth1
valid_lft forever preferred_lft forever
40424: eth0@if40425: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether f2:c8:73:a7:5c:9c brd ff:ff:ff:ff:ff:ff
inet 192.168.0.38/23 scope global eth0
valid_lft forever preferred_lft forever
端的な表示だとこちら。
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242484488eb no vethb06656b
インスタンス情報からもネットワークについて確認できます。
$ docker inspect ngtest
かなり分量がありますが、今回見れば良いところは下記です。
[
(略)
"NetworkSettings": {
"Bridge": "",
(略)
"Ports": {
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "80"
}
]
(略)
"Gateway": "172.17.0.1",
(略)
"IPAddress": "172.17.0.2",
(略)
]
Docker ネットワーク構築 ハンズオン
次に、新しいネットワーク(Bridge)を作ってみましょう。
$ docker network create b2
そうすると、下記のように追加されます。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
188fc492cab7 b2 bridge local
c248babe0bdd bridge bridge local
97c31c8afe7b host host local
e950afaacc2f none null local
次のコマンドでもそれぞれ確認すると良いでしょう。
ip a
ifconfig -a
作成した新しいネットワークに接続したコンテナを生成・起動します。
docker run --name ngtestb2 --network=b2 -p 8080:80 -d nginx
先程起動した Nginx コンテナとは別ポートにしている点は注意です。被ると怒られます。
それでは、この作成したネットワークに対して操作してみます。
$ docker run --network=b2 -it --name al1 alpine
# wget ngtestb2:80
Connecting to ngtestb2:80 (172.19.0.2:80)
index.html 100% |*************************| 612 0:00:00 ETA
# wget ngtest:80
wget: bad address 'ngtest:80'
# wget 172.17.0.2:80
Connecting to 172.17.0.2:80 (172.17.0.2:80)
これが何を意味しているかというと、下記の通りです。
- b2ネットワークに接続した alpineコンテナ al1 のシェルを起動した
- 同じb2ネットワークにある ngtestb2 のHTTPサーバへの接続が成功した
- 異なるネットワークにある ngtest のHTTPサーバへの接続が失敗した
このようにネットワークを分離することができました。このように、1つのdocker内で異なるネットワークを構成することが可能なことが分かりました。
最後に、コンテナを複数のネットワークに接続してみます。Ctrl+P、Ctrl+q でデタッチして、下記のコマンドを実行します。
docker network connect bridge al1
この状態で、再度疎通確認をしてみます。
$ docker attach al1
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:13:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.3/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
24: eth1@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth1
valid_lft forever preferred_lft forever
# wget ngtestb2:80
Connecting to ngtestb2:80 (172.19.0.2:80)
index.html 100% |*************************| 612 0:00:00 ETA
# wget ngtest:80
wget: bad address 'ngtest:80'
# ping 172.17.0.2
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.173 ms
(略)
2つの仮想NICが接続されていることがわかります。
ネットワークが異なると名前解決はできませんが、IPでの疎通はできることがわかります。
このように、1つのコンテナに複数のNICを利用することが可能です。
課題2 |
---|
次のコマンドを駆使して、作成した b2 ネットワークを削除しましょう |
docker network rm |
docker network disconnect |
Docker ストレージ管理
これまでなんとなくコンテナ内にファイルを保存したり、操作したりしてきました。
しかし、実際のDocker 内のファイルシステムは、ホストOSに形成されています。
Play with Docker のディレクトリは /var/lib/docker/overlay2/ 配下にコンテナを形成するファイル群が配置されています。
それぞれのコンテナは、ディレクトリごと分離されいるため、相互のファイルへ関与し合うことはありません。逆に、設定無しには操作し合うことできません。
ホストOS および 複数のコンテナでは「ボリューム」と呼ぶ領域をマウントできます。そこでファイルの共有ができるわけです。
この仕組みを理解すると、コンテナ間のファイル共有はもちろん、データを永続化できます。つまり、一時的に作成するコンテナのデータをホストOSに保存することで、データを使い回すことが可能になります。
例えば、MySQL コンテナのデータベースデータをボリュームに作成することで、そのコンテナを停止しても、データ自体はホストに保存しておけるわけです。
詳しくは下記のドキュメントを読むと良いでしょう。
- Use volumes | Docker Documentation ※英語
- Docker ストレージ・ドライバ — Docker-docs-ja 17.06.Beta ドキュメント
- CCompose ファイル・リファレンス — Docker-docs-ja 17.06.Beta ドキュメント
- volume - 入門 Docker
- Docker の基本学習 ~ Docker のネットワーク
- Docker、ボリューム(Volume)について真面目に調べた - Qiita
Dockerストレージ管理 ハンズオン1
コンテナとホストを繋ぐボリュームを作成してみます。
docker run -v /tmp/test alpine touch /tmp/test/test.txt
作成した結果のボリューム状態はこちら。
$ docker volume ls
DRIVER VOLUME NAME
local a9afbc9a643b984076e232f8d8f467f658ba2b24fdd848c6e6181a67e74d5a01
正直よくわからないので、上記の VOLUME NAME を指定して詳細を確認します。
$ docker volume inspect a9afbc9a643b984076e232f8d8f467f658ba2b24fdd848c6e6181a67e74d5a01
[
{
"CreatedAt": "2019-09-01T07:56:33Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/a9afbc9a643b984076e232f8d8f467f658ba2b24fdd848c6e6181a67e74d5a01/_data",
"Name": "a9afbc9a643b984076e232f8d8f467f658ba2b24fdd848c6e6181a67e74d5a01",
"Options": null,
"Scope": "local"
}
]
Mountpoint の値に指定してある箇所がホストと共有(マウント)している領域となります。
マウントできているか確認しましょう。
$ ls -l /var/lib/docker/volumes/a9afbc9a643b984076e232f8d8f467f658ba2b24fd
d848c6e6181a67e74d5a01/_data/test.txt
-rw-r--r-- 1 root root 0 Sep 1 07:56 /var/lib/docker/volumes/a9afbc9a643b984076e232f8d8f467f658ba2b24fdd848c6e6181a67e74d5a01/_data/test.txt
ホストにマウントできていることは分かりました。しかし、このままでは使いづらいです。もうちょっと短い名前でマウントしてみましょう。
$ mkdir /tmp/test
$ docker run -v /tmp/test:/tmp/test --name al5 alpine touch /tmp/test/test.txt
$ ls -l /tmp/test/
total 0
-rw-r--r-- 1 root root 0 Sep 1 08:05 test.txt
-v {ホストのディレクトリパス (絶対パス)}:{コンテナのディレクトリパス} のように指定すると、任意のディレクトリを共有することができます。ただし、使用するパスは絶対パスにする必要があるので注意です。
Dockerストレージ管理 ハンズオン2
コンテナ間でボリュームを共有してみましょう。
まず、ボリュームをマウントしたコンテナを起動しましょう。
docker run --name al10 -v /tmp/t1 alpine touch /tmp/t1/share-test1.txt
もう一つ、別のコンテナで先に作成したコンテナを起動しましょう。ポイントは --volumes-from です。
$ docker run --volumes-from al10 alpine ls -l /tmp/t1
total 0
-rw-r--r-- 1 root root 0 Sep 1 09:34 share-test1.txt
無事にファイル共有できていることが確認できました。
ただ、一時的に起動するコンテナ同士でデータ共有するには、ホストに保存した方が良いかも知れませんね。
Docker 運用管理
Docker コンテナ/イメージの管理コマンド
これまで紹介してきた以外に、実運用で利用するコマンドを紹介します。
これらは運用作業やトラブルシューティングに活用しますので、しっかり覚えましょう。
Docker コンテナの詳細情報
コンテナの詳細情報を確認します。
docker inspect {CONTAINER ID|NAMES} (正式には docker container inspect {CONTAINER ID|NAMES} )
JSON形式で、かなり詳細なコンテナインスタンスの情報が確認できます。
$ docker inspect XXXXXXXXXXXX
[
{
"Id": "f1a6b55da1b093da415e654c56207983170842de4ac303dde528c9db71106cf7",
"Created": "2019-08-30T08:45:49.522153709Z",
"Path": "/bin/sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 16528,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-08-30T08:45:50.044285658Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4",
"ResolvConfPath": "/var/lib/docker/containers/f1a6b55da1b093da415e654c56207983170842de4ac303dde528c9db71106cf7/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/f1a6b55da1b093da415e654c56207983170842de4ac303dde528c9db71106cf7/hostname",
"HostsPath": "/var/lib/docker/containers/f1a6b55da1b093da415e654c56207983170842de4ac303dde528c9db71106cf7/hosts",
"LogPath": "/var/lib/docker/containers/f1a6b55da1b093da415e654c56207983170842de4ac303dde528c9db71106cf7/f1a6b55da1b093da415e654c56207983170842de4ac303dde528c9db71106cf7-json.log",
"Name": "/musing_solomon",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/5deef75b0a4c64d1520520142487c22cd7c9fea8e3e7a86adcc00378394fe8e2-init/diff:/var/lib/docker/overlay2/cf8a2394f09105178932b8e6bdeb28ebfa4dd8c4d38a6fbf30f6c3e9d494bee0/diff",
"MergedDir": "/var/lib/docker/overlay2/5deef75b0a4c64d1520520142487c22cd7c9fea8e3e7a86adcc00378394fe8e2/merged",
"UpperDir": "/var/lib/docker/overlay2/5deef75b0a4c64d1520520142487c22cd7c9fea8e3e7a86adcc00378394fe8e2/diff",
"WorkDir": "/var/lib/docker/overlay2/5deef75b0a4c64d1520520142487c22cd7c9fea8e3e7a86adcc00378394fe8e2/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "f1a6b55da1b0",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": true,
"OpenStdin": true,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
],
"Image": "alpine",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "5fc2b5a75f31235374a65d3b676082c3acb185e1312a55902eb4e78048092f19",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/5fc2b5a75f31",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "f8684a1a1f53f7286bac6569f08b7d46e774447a01bc160ffde32eaec49c2f6d",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "4c20e0305bd0a133a24086e96de1dd17f814b600a4fc10ae46c9bdbf4e6139ec",
"EndpointID": "f8684a1a1f53f7286bac6569f08b7d46e774447a01bc160ffde32eaec49c2f6d",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
このコマンドは、停止したインスタンスに対しても実行可能です。
リファレンス:inspect — Docker-docs-ja 17.06.Beta ドキュメント
Docker イメージの詳細情報
イメージの詳細情報を確認します。
docker inspect {IMAGE ID| REPOSITORY} (正式には docker image inspect {IMAGE ID | REPOSITORY} )
JSON形式で、かなり詳細なイメージの情報が確認できます。
$ docker image inspect alpine
[
{
"Id": "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4",
"RepoTags": [
"alpine:latest"
],
"RepoDigests": [
"alpine@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb"
],
"Parent": "",
"Comment": "",
"Created": "2019-08-20T20:19:55.211423266Z",
"Container": "0a80155a31551fcc1a36fccbbda79fcd3f0b1c7d270653d00310e6e2217c57e6",
"ContainerConfig": {
"Hostname": "0a80155a3155",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/sh\"]"
],
"ArgsEscaped": true,
"Image": "sha256:06f4121dff4d0123ce11bd2e44f48da9ba9ddcd23ae376ea1f363f63ea0849b5",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "18.06.1-ce",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
],
"ArgsEscaped": true,
"Image": "sha256:06f4121dff4d0123ce11bd2e44f48da9ba9ddcd23ae376ea1f363f63ea0849b5",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 5581746,
"VirtualSize": 5581746,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/cf8a2394f09105178932b8e6bdeb28ebfa4dd8c4d38a6fbf30f6c3e9d494bee0/merged",
"UpperDir": "/var/lib/docker/overlay2/cf8a2394f09105178932b8e6bdeb28ebfa4dd8c4d38a6fbf30f6c3e9d494bee0/diff",
"WorkDir": "/var/lib/docker/overlay2/cf8a2394f09105178932b8e6bdeb28ebfa4dd8c4d38a6fbf30f6c3e9d494bee0/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
リファレンス:inspect — Docker-docs-ja 17.06.Beta ドキュメント
Docker コンテナの差分表示
コンテナ上で、変更されたファイルやディレクトリの一覧を表示します。
docker diff {CONTAINER ID|NAMES} (正式には docker container diff {CONTAINER ID|NAMES} )
$ docker diff XXXXXXXXXXXX
C /usr
C /usr/local
C /usr/local/lib
C /usr/local/lib/python3.6
C /usr/local/lib/python3.6/__pycache__
A /usr/local/lib/python3.6/__pycache__/io.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/_sysconfigdata_m_linux_x86_64-linux-gnu.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/_weakrefset.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/codecs.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/genericpath.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/site.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/stat.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/sysconfig.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/_bootlocale.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/abc.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/os.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/_collections_abc.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/_sitebuiltins.cpython-36.pyc
A /usr/local/lib/python3.6/__pycache__/posixpath.cpython-36.pyc
C /usr/local/lib/python3.6/encodings
C /usr/local/lib/python3.6/encodings/__pycache__
A /usr/local/lib/python3.6/encodings/__pycache__/aliases.cpython-36.pyc
A /usr/local/lib/python3.6/encodings/__pycache__/latin_1.cpython-36.pyc
A /usr/local/lib/python3.6/encodings/__pycache__/utf_8.cpython-36.pyc
A /usr/local/lib/python3.6/encodings/__pycache__/__init__.cpython-36.pyc
具体的に、どんなファイルが変更されたのかを知るのに役立ちます。
リファレンス:diff — Docker-docs-ja 17.06.Beta ドキュメント
Docker コンテナ構築の履歴表示
イメージの最新レイヤをどのように構築したか確認します。
docker history {REPOSITORY ID|NAMES} (正式には docker image history {REPOSITORY ID|NAMES} )
実際の表示は下記です。
$ docker history alpine
IMAGE CREATED CREATED BY SIZE COMMENT
961769676411 9 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 9 days ago /bin/sh -c #(nop) ADD file:fe64057fbb83dccb9… 5.58MB
docker:scm というようにタグを指定すると最新以外も指定可能です。
$ docker history docker:scm
IMAGE CREATED CREATED BY SIZE COMMENT
2ac9d1098bf1 3 months ago /bin/bash 241.4 MB Added Apache to Fedora base image
88b42ffd1f7c 5 months ago /bin/sh -c #(nop) ADD file:1fd8d7f9f6557cafc7 373.7 MB
c69cab00d6ef 5 months ago /bin/sh -c #(nop) MAINTAINER Lokesh Mandvekar 0 B
511136ea3c5a 19 months ago 0 B Imported from -
リファレンス:history — Docker-docs-ja 17.06.Beta ドキュメント
Docker コンテナのログ表示
コンテナ(インスタンス)内に出力された標準出力(STDOUT)と標準エラー出力(STDERR)を確認できます。
docker logs {CONTAINER ID|NAMES} (正式には docker image logs {CONTAINER ID|NAMES} )
コンテナが起動しないなど、トラブルシューティングの役に立ちます。起動しているコンテナについて実行してみましょう。
docker logs alpine
アクセスログなどを流しっぱなしにする tail -f と同じような使い方をしたい場合は、下記のコマンドで実行します。
docker logs -f nginx_http
利用パターンは下記のページで詳しく紹介されていますので、ご覧ください。
リファレンス:logs — Docker-docs-ja 17.06.Beta ドキュメント
Docker コンテナ/イメージの掃除
停止しているコンテナ および 不要なイメージの一括削除ができます。
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
7215e569000e514defa362057f89c37b54c16a83f0b398ee3c456e6246c6c90c
23bdc90a405cf539adb5f7f6bb7c8e027640dd0e4cc03112b98e2d619a37099f
4942e9d768d8d0795a830848f7a98b21ebe0e4a9d1bda3cf6d75bc04e0f204bf
$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
ちょっと危険なので、本番運用では使わないかも知れませんが、便利ではありますね。
Docker サービス管理
Docker サービス情報
Docker サービス自体のシステム情報を表示します。
$ docker system info
Client:
Debug Mode: false
Server:
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 5
Server Version: 19.03.1
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc version: 425e105d5a03fabd737a126ad93d62a9eeede87f
init version: fec3683
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 4.4.0-154-generic
Operating System: Alpine Linux v3.10 (containerized)
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 31.4GiB
Name: node1
ID: 6U4B:34PI:LLBI:KGVS:KQ3W:VB25:GXGU:VOUE:TNDJ:VA4W:DXRC:2I72
Docker Root Dir: /var/lib/docker
Debug Mode: true
File Descriptors: 29
Goroutines: 47
System Time: 2019-08-30T09:26:01.521391088Z
EventsListeners: 0
Registry: https://index.docker.io/v1/
Labels:
Experimental: true
Insecure Registries:
127.0.0.1
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
WARNING: API is accessible on http://0.0.0.0:2375 without encryption.
Access to the remote API is equivalent to root access on the host. Refer
to the 'Docker daemon attack surface' section in the documentation for
more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
WARNING: No swap limit support
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
他人が建てた Docker を利用する際には有効でしょう。
Docker ボリューム情報
Docker サービス自体のボリューム情報を表示します。
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 5 1 2.702GB 2.696GB (99%)
Containers 1 1 0B 0B
Local Volumes 2 0 249.5MB 249.5MB (100%)
Build Cache 0 0 0B 0B
Docker 自体がどれだけ容量を使用しているのかが分かります。ディスク容量を減らしたい場合などに有効です。
Docker / Docker-compose の豊富な機能
さらに Docker / Docker-compose の豊富な機能を活用するには、下記のリファレンスを眺めると良いでしょう。
Engine リファレンス — Docker-docs-ja 17.06.Beta ドキュメント
さらに最新版のリファレンスが欲しい場合は下記を利用しましょう。
docker | Docker Documentation(注:英語)
Docker の構造とセキュリティ
Docker 基盤の詳細な構成やセキュリティに関して、下記が分かり易いのでオススメです。
問題(宿題)
WordPress サイトを次の状態で構築しましょう。
- WordPress / MySQL / Nginx の3コンテナで構成する
- MySQL のデータベースデータをホストに保存する
- Nginx でリバースプロキシを構成する
- WordPressの記事データは theme-test-data-ja を使用する
- 80番ポートに接続すると Nginx経由 、8080ポートは WordPress へ直接できるようにすること
- NginxコンテナからはMySQLコンテナに直接接続できないようにすること
おわりに
今回は docker コンテナを管理する方法について、ハンズオンをしました。
ようやく現実的な運用に利用できる状態となってきましたが、大量のコンテナ操作や定型的な運用操作の効率化を考えると、Docker Compose では物足りません。
そこでいよいよ Kubernetes というオーケストレーションツールの出番となります。
それはまた次のハンズオンで学習しましょう。
コンテナ技術 ハンズオン Vol.5 Kubernetes編
参考
これまでに紹介した記事以外に、本ハンズオン資料を作成する上で下記の記事を参考にさせていただきました。
- Overview of Docker Compose | Docker Documentation
- Docker Engine — Docker-docs-ja 17.06.Beta ドキュメント
- Docker入門-基礎編 いまから始めるDocker管理【2nd Edition】
- 入門 Docker
- Use the Docker command line | Docker Documentation
- Dockerのすべてが5分でわかるまとめ!(コマンド一覧付き) - paiza開発日誌
- Dockerハンズオン基礎編:コンテナとイメージのライフサイクルを理解 - Qiita
- こうしたいんだぜ! という時の逆引きdockerコマンド | 株式会社ビヨンド
大変ありがとうございました。