Docker Remote APIを使ってみる #apijp
このエントリは「Web API Advent Calendar 2014」の12/3担当です。次は「YosAwed」さんです。
最近話題のDockerですが、みなさんもう使ってますよね?
Dockerはクライアント-サーバーアーキテクチャを採用しており、DockerクライアントとDockerサーバーがRemote API経由で接続されています。つまり、「docker ps」などのコマンドはすべてサーバーに送られて処理されているということです。
このRemote API、実は(ほぼ)RESTになっていて、Dockerクライアント以外からでも利用することが可能です。そこで、Remote APIを直接使う方法についてご紹介したいと思います。
テストした環境
Mac OS X(Yosemite)のBoot2Dockerを利用しました。Linux環境でもDockerサーバーの設定だけ追加すれば大丈夫なはずです。
$ docker version Client version: 1.3.2 Client API version: 1.15 Go version (client): go1.3.3 Git commit (client): 39fa2fa OS/Arch (client): darwin/amd64 Server version: 1.3.2 Server API version: 1.15 Go version (server): go1.3.3 Git commit (server): 39fa2fa $ boot2docker version Boot2Docker-cli version: v1.3.2 Git commit: e41a9ae
Docker Remote APIを使うための設定
LinuxのDockerサーバーは、デフォルトではUnixドメインソケット(unix:///var/run/docker.sock)をリスンするように設定されています。
このままではリモートからTCP接続できないので、Dockerサーバーの起動時オプションに '-H tcp://0.0.0.0:2376' のようにしてTCPのリスンポートを追加する必要があります。
設定方法としては、dockerコマンドの起動時オプションで指定するか、設定ファイルに追記するなど、いくつかやり方があります。
例えばUbuntu14.04では /etc/init/docker.conf に
DOCKER_OPTS=' -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock'
を設定し、
$ sudo service docker restart
で反映します。
詳しくはDockerの公式ドキュメントを参照してください。
https://docs.docker.com/articles/basics/#bind-docker-to-another-hostport-or-a-unix-socket
Boot2Dockerの場合
Boot2Dockerの場合はもともとTCPで接続するようになっているので、特に設定は必要ありません。
DockerサーバーのTCP接続先は「boot2docker shellinit」で確認できます。
$ boot2docker shellinit Writing /Users/nobusue/.boot2docker/certs/boot2docker-vm/ca.pem Writing /Users/nobusue/.boot2docker/certs/boot2docker-vm/cert.pem Writing /Users/nobusue/.boot2docker/certs/boot2docker-vm/key.pem export DOCKER_CERT_PATH=/Users/nobusue/.boot2docker/certs/boot2docker-vm export DOCKER_TLS_VERIFY=1 export DOCKER_HOST=tcp://192.168.59.103:2376
TCP接続先はBoot2DockerのVMを再起動すると変わることがあるので、以下のコマンドで環境変数を毎回設定しましょう。
$ $(boot2docker shellinit 2>/dev/null)
また、Boot2Docker VMのIPアドレスを毎回手打ちするのは面倒なので、以下のコマンドでhostsに登録しておきましょう。(Mac限定)
$ sudo sed -i -e '/dockerhost/d' /etc/hosts $ echo $(boot2docker ip 2>/dev/null) dockerhost | sudo tee -a /etc/hosts
これでBoot2Docker VMを「dockerhost」で参照できます。
以降はこの設定を前提として記載しますので、未設定の方は適宜IPアドレスに読み替えてください。
Docker Remote APIでイメージ一覧を取得する
当然ですが、事前にDockerサーバーを起動しておいてください。(Boot2Dockerの方は boot2docker up しておいてください。)
また、wgetやcurlなど、RESTのリクエストを送信できるコマンドをインストールしておいてください。
(筆者の環境ではcurlは証明書の処理でエラーが発生したため、wgetを利用しています。また、JSONを見やすく整形するためにjqコマンドを利用します。)
Dockerを初めて使う方は「docker pull」で適当なイメージをダウンロードしておいてくださいね。その上でイメージ一覧を確認しておきましょう。
$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE oddpoet/zookeeper latest 33a69da2484d 5 days ago 909.3 MB nobusue/kafka 0.8.1.1 29836f0457d5 5 days ago 808.1 MB nobusue/java7 u72 140a4d7d1cea 5 days ago 500.6 MB
それではRESTで同じ情報が取れるか確認してみましょう。
まず、DockerサーバーのTCP接続先を確認します。
ここでは、「DOCKER_HOST=tcp://192.168.59.103:2376」を前提としてコマンドを実行例を記載します。
次に、おもむろにRESTリクエストを送信してみましょう。
$ wget http://dockerhost:2376/images/json -O - -q | jq .
Linux環境ではJSONが表示されたと思いますが、Boot2Docker環境では何も表示されないはずです。
実は、Boot2Docker環境ではTLS暗号化が行われており、証明書と秘密鍵の指定が必要です。以下のようにしてください。
$ wget --no-check-certificate --certificate=$DOCKER_CERT_PATH/cert.pem --private-key=$DOCKER_CERT_PATH/key.pem https://dockerhost:2376/images/json -O - -q | jq .
正常に実行できれば、こんな感じのレスポンスが返ってきます。
[ { "Created": 1417099585, "Id": "33a69da2484d70d6e9b9e590b6286a4fe6fba5ab91a7444ba6d970a7c97e10d8", "ParentId": "47f7486b7c978fda52628680274d3e0aeaa504c027b48fca1b898755ef21eedd", "RepoTags": [ "oddpoet/zookeeper:latest" ], "Size": 0, "VirtualSize": 909336287 }, { "Created": 1417088378, "Id": "29836f0457d5f82b748c42d3ed8f798086f8116b09b700e3c1f36d058404de62", "ParentId": "d53de445c803da52a60af0cde9f8448f4f1b34422129e5234c1e2ffa6ec09b67", "RepoTags": [ "nobusue/kafka:0.8.1.1" ], "Size": 0, "VirtualSize": 808064814 }, { "Created": 1417080614, "Id": "140a4d7d1cea6982b3d62921d3edb509f2602c8bda69f99a2c6ca0e055f39f1c", "ParentId": "0d7c4caeafc408f94009cc6f8d6cf52a8412a81dd6158ee40dde18715ce115de", "RepoTags": [ "nobusue/java7:u72" ], "Size": 0, "VirtualSize": 500624405 } ]
「docker images」コマンドと同等の情報が得られることが確認できました。
Docker Remote APIでコンテナ一覧を取得する
次に、コンテナ一覧を取得してみます。
先に適当なコンテナを起動しておきましょう。
$ docker run -ti -d ubuntu $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 91d01d7df230 ubuntu:latest "/bin/bash" 7 seconds ago Up 6 seconds cranky_ardinghelli
RESTでコンテナ一覧を取得してみます。
$ wget --no-check-certificate --certificate=$DOCKER_CERT_PATH/cert.pem --private-key=$DOCKER_CERT_PATH/key.pem https://dockerhost:2376/containers/json -O - -q | jq . [ { "Command": "/bin/bash", "Created": 1417537292, "Id": "91d01d7df23053c8bac8b3ccdd8a02015027da69a0b57a8a1e8b6b66f1477c7f", "Image": "ubuntu:latest", "Names": [ "/cranky_ardinghelli" ], "Ports": [], "Status": "Up 22 seconds" } ]
簡単ですね!
その他のAPIの使い方
公式リファレンスを参照してください。
Docker Remote API - Docker Documentation
なお、Remote APIにはバージョンがあり、DockerサーバーとDockerクライアントでAPIバージョンが異なると接続できません。
自分でRESTを叩く場合には問題ないかもしれませんが、独自のクライアントを実装する場合などは注意してください。
(補足)Unixドメインソケットを覗き見する
socatコマンドでドメインソケットを覗き見できます。デバッグのときなどにどうぞ。
How to set the name of a Docker container using REST API - Stack Overflow