LoginSignup
6

More than 3 years have passed since last update.

コンテナ技術 ハンズオン Vol.4 Docker管理編

Last updated at Posted at 2019-09-01
1 / 29

本題の前に


位置付け・前提

本記事は、社内ワークショップ のために用意したものです。そのため、次の前提で進めることをご理解ください。

また、本稿はこちらの続きとなります。

コンテナ技術 ハンズオン Vol.1 Docker操作編
コンテナ技術 ハンズオン Vol.2 Dockerイメージ編
コンテナ技術 ハンズオン Vol.3 Docker Compose編

目的や前提なども上記の内容に準拠します。


docker ハンズオン環境

今回も Play with Docker を活用してハンズオンを行います。

playwithdocker.png

※要:Docker Hub アカウント

注意点として、この環境は4時間の制限があります。4時間経過すると環境が削除されてしまう点を注意して下さい。

もちろんローカル環境でも構いません。


ハンズオン


今回のゴール

  • Docker のリソースを制御できるようになる
  • Docker のトラブルシューティングができるようになる

今回やらないこと

  • kubernetes などのオーケストレーションツールは使いません。

Docker リソース管理


Docker ネットワーク管理

これまでなんとなくポートの紐付けを設定したりしてきました。実は、Docker 内でネットワークを形成しています。

Docker 標準ネットワークモデル

実は Docker 内でIPアドレスもポート番号も保有しており、TCP/IPネットワークを形成することが可能です。

仕組みとしては、brige / host / none の3パターンです。

brige≒NAPThost=ホストNIC共有none=Docker内のクローズドネットワークと覚えると良いでしょう。(ポートフォワードするので、NATというよりNAPT)

コンテナのネットワーク接続

どの bridge に接続するかを選択でき、複数接続することも可能です。

ちなみに、これまで Dockerfile/Docker Compose で活用してきた links 指定は、今後廃止されていく可能性があるそうです。

詳しくは下記のドキュメントを読むと良いでしょう。


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に形成されています。

Docker データの扱い

Play with Docker のディレクトリは /var/lib/docker/overlay2/ 配下にコンテナを形成するファイル群が配置されています。

それぞれのコンテナは、ディレクトリごと分離されいるため、相互のファイルへ関与し合うことはありません。逆に、設定無しには操作し合うことできません。

Docker データボリューム

ホストOS および 複数のコンテナでは「ボリューム」と呼ぶ領域をマウントできます。そこでファイルの共有ができるわけです。

Docker データボリュームの構成

この仕組みを理解すると、コンテナ間のファイル共有はもちろん、データを永続化できます。つまり、一時的に作成するコンテナのデータをホストOSに保存することで、データを使い回すことが可能になります。

例えば、MySQL コンテナのデータベースデータをボリュームに作成することで、そのコンテナを停止しても、データ自体はホストに保存しておけるわけです。

詳しくは下記のドキュメントを読むと良いでしょう。


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

利用パターンは下記のページで詳しく紹介されていますので、ご覧ください。

Docker調査 ~ログ編~

リファレンス: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 Site

  • WordPress / MySQL / Nginx の3コンテナで構成する
  • MySQL のデータベースデータをホストに保存する
  • Nginx でリバースプロキシを構成する
  • WordPressの記事データは theme-test-data-ja を使用する
  • 80番ポートに接続すると Nginx経由 、8080ポートは WordPress へ直接できるようにすること
  • NginxコンテナからはMySQLコンテナに直接接続できないようにすること

おわりに

今回は docker コンテナを管理する方法について、ハンズオンをしました。

ようやく現実的な運用に利用できる状態となってきましたが、大量のコンテナ操作定型的な運用操作の効率化を考えると、Docker Compose では物足りません。
そこでいよいよ Kubernetes というオーケストレーションツールの出番となります。

それはまた次のハンズオンで学習しましょう。

コンテナ技術 ハンズオン Vol.5 Kubernetes編


参考

これまでに紹介した記事以外に、本ハンズオン資料を作成する上で下記の記事を参考にさせていただきました。

大変ありがとうございました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6