はじめに
最近マッサージ機を使っている時にふくらはぎのツボを見つけた、けんつです。
この時期は、Muroran Institute of Technology Advent Calendar 2018 16日目の記事です。
今取り組んでいるプロジェクトで、最近話題のk8sを使わずにdockerコンテナをいい感じに制御する必要があり 「Docker Remote API」 なるものを使い倒しているので今回はその概要と利用方法をざっくりとまとめようかなと思っています。
具体的な例は後日、別日のアドカレで書きます。
Docker の 基本的な仕組み
Dockerの仕組みといっても、大体は以下の記事に書いてあることを中心に特に Docker Remote API に関することを書きます。
というか、なぜ Docker Remote API があるのか。みたいなことを話すのに Docker の超基本的な仕組みを紹介する必要があるからです。
Docker は以下のようなクライアント-サーバアーキテクチャを採用している。
これらは主要な3つのコンポーネントによって成立している。
よく、 docker ps などコマンドを使うと思うがこれはコマンドがクライアントの役割を担っていて Docker Remote API を叩くことで Docker Daemon が処理を行うという構成になっている。
Docker の アーキテクチャ
基本的な仕組みは上で解説したとおりで、次は重要となるアーキテクチャ部分を詳解する。
Docker のアーキテクチャは以下のようになっている。
それぞれの役割を以下にまとめる。
Docker Daemon
Docker Daemon(dockerd) は Docker APIコール を listen して、コンテナ、ボリューム、ネットワークなど Docker で必要となるオブジェクトを管理する。
そしてこの Daemonは他のDaemonと通信することも出来る。
Docker Remote API とは
上記の説明でわかったと思うが、実際に docker コマンドなどがコールしているAPIがそれに当てはまる。
Docker コマンドは単にクライアントにすぎないのでDocker コマンドでなくてもこのAPIをコールすることができ、コンテナの作成削除、はたまたコンテナ内の標準入出力なども取得することができる。
ここでは、その利用方法と簡単な例をあげようと思う。
準備
Docker Remote APIはそのまま使うことはできない。
というのも、デフォルトでは Unix Domain Socketでのみ利用可能になっているからだ。
まず、Docker Remote API を利用する場合に Unix Domain Socket だけでなく TCP を使えるようにする必要がある。
Ubuntu の場合は /etc/init/docker.conf に
DOCKERD=/usr/bin/dockerd
DOCKER_OPTS="-d -H=tcp://127.0.0.1:4243"
とある部分の、 DOCKER_OPTSで 127.0.0.1 、 4243ポートでTCPを許可する一文をいれてからデーモンを再起動することで使えるようになる。
TCPでいけるということは curl などを使ってHTTPリクエストでいけるということになる。
これで行けない場合が存在するらしいがその時は /lib/systemd/system/docker.service で
ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0:4243
とするといけるそう。
実際のシステムで運用する際などには、これではちょっとまずいことになるので証明書などを導入するべき。
Protect the Docker daemon socket | Docker Documentation
そこら辺が面倒ならUnix Domain Socketを利用するとよいかもしれない。
これで準備は完了した。
利用例
利用例の一部を紹介する。
コンテナ一覧を取得
試しに、redisコンテナを起動させた状態でやってみた。
$ curl http://127.0.0.1:4243/containers/json
[ { "Id": "249a982a42823380db8703966915dca91548f945bb109beaff31926f85d007a8", "Names": [ "/accepted_redis_1_b573c8ffd990" ], "Image": "redis:latest", "ImageID": "sha256:c188f257942c5263c7c3063363c0b876884eb458d212cf57aa2c063219016ace", "Command": "docker-entrypoint.sh redis-server --appendonly yes", "Created": 1544365476, "Ports": [ { "IP": "0.0.0.0", "PrivatePort": 6379, "PublicPort": 6379, "Type": "tcp" } ], "Labels": { "com.docker.compose.config-hash": "69b24a42ee98408e3e9622311382cc47736de52c1bdc8a578731e06673db2f26", "com.docker.compose.container-number": "1", "com.docker.compose.oneoff": "False", "com.docker.compose.project": "accepted", "com.docker.compose.service": "redis", "com.docker.compose.slug": "b573c8ffd9903731bccd479f3086b206bee4d6ac4e66e89da012e25b21743bb", "com.docker.compose.version": "1.23.0" }, "State": "running", "Status": "Up 6 days", "HostConfig": { "NetworkMode": "accepted_default" }, "NetworkSettings": { "Networks": { "accepted_default": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "da9a9b579158911ba56881af6149f37f2a9a7cc35cf2348183ddf9db75642cab", "EndpointID": "5a4ea6f575af66bb0ee307dcc82ea6aeb85517f5daf3a02e58f447336ad75631", "Gateway": "172.18.0.1", "IPAddress": "172.18.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:12:00:02", "DriverOpts": null } } }, "Mounts": [ { "Type": "volume", "Name": "d5c83c863897ed4a0f6bab5dc55e56744fb5edf3a284fcae0e7161f61b1670aa", "Source": "", "Destination": "/data", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ] } ]
コンテナを作成
$ curl -X POST -H "Content-Type: application/json" http://localhost:4243/containers/create -d '{"Hostname":"","User":"","Memory":0,"MemorySwap":0,"AttachStdin":false,"AttachStdout":true,"AttachStderr":true,"PortSpecs":null,"Privileged": false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Dns":null,"Image":"nginx","Volumes":{},"VolumesFrom":[],"WorkingDir":""}' {"Id":"2bdb551799ccff923a417dac1135c190dcb16b9429eca9cb9eb5daffd4a69751","Warnings":null}
これで起動すると docker ps ではコンテナが見えないらしく docker ps -a で全てのコンテナを参照する必要がある。
また手元にイメージのないコンテナは一度 pull 必要がある。
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2bdb551799cc nginx "nginx -g 'daemon of…" 45 seconds ago Created
コンテナを止める
さっきたてたコンテナを止める
curl -X POST http://localhost:4243/containers/2bdb551799ccff923a417dac1135c190dcb16b9429eca9cb9eb5daffd4a69751/stop
これで止まる。コンテナIDではなくコンテナ名でもよさげ