Python の学習がてら、SDKs for Docker Engine API を触ってみた
はじめに
Python の学習を始めるにあたり、手頃なお題を探していました。 Docker Engine API を利用すると、各種コードからコンテナが起動出来るということを docker docs - SDKs for Docker Engine API で知り 試しに動かしてみようと思いました。
なお、筆者は Python 初心者であるため 記述内容に不備などあれば、ご指摘頂けますと幸いです。
事前作業
Docker SDK for Python は、Python Package Index (PyPI) で パッケージとして提供されているため、pip でインストール出来ます。 以下のコマンドにて、予めインストールしておいてください。 なお、筆者の環境は macOS Sierra(10.12.4) です。
$ sudo pip install docker
はじめてみよう
以下のドキュメントに記載されたサンプルを動かしてみながら、Docker API を試してみましょう。
Run a container
まずは、コンテナを起動するコードを記述します。 ファイル名は、run_container.py としました。
#!/usr/bin/env python # -*- coding: utf-8 -*- import docker client = docker.from_env() print client.containers.run("alpine", ["echo", "hello", "world"])
実行してみます。
~/local/sample $ ./run_container.py hello world
"hello world"は、echo されましたが、 コンテナ内で実行されたかどうか分からないので プログラムコードをループ処理に変更(daemonize)し、 docker コマンドにて、確認してみます。
コードの変更点は、以下のとおりです。
~/local/sample $ git diff ^HEAD diff --git a/run_container.py b/run_container.py index 2b3e547..7dcbd9d 100755 --- a/run_container.py +++ b/run_container.py @@ -3,4 +3,4 @@ import docker client = docker.from_env() -print client.containers.run("alpine", ["echo", "hello", "world"]) +print client.containers.run("alpine", ["sh", "-c", 'while true; do echo hello world; sleep 1; done']) ~/local/sample $
バックグラウンドで実行し、docker コマンドで確認してみましょう。
~/local/sample $ ./run_container.py > /dev/null & [1] 3598 ~/local/sample $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 08f51295d34c alpine "sh -c 'while true..." 15 seconds ago Up 14 seconds jovial_wescoff ~/local/sample $ docker top 08f51295d34c PID USER TIME COMMAND 4452 root 0:00 sh -c while true; do echo hello world; sleep 1; done 4500 root 0:00 sleep 1 ~/local/sample $ docker logs 08f51295d34c | tail hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world
確かに、alpine イメージのコンテナが起動され延々と "hello world" が出力されているようです。
Run a container in the background
次に、バックグラウンドでコンテナを起動してみます。
コードの変更点は、以下のとおりです。
~/local/sample $ git diff ^HEAD diff --git a/run_container.py b/run_container.py index 7dcbd9d..185d72a 100755 --- a/run_container.py +++ b/run_container.py @@ -3,4 +3,5 @@ import docker client = docker.from_env() -print client.containers.run("alpine", ["sh", "-c", 'while true; do echo hello world; sleep 1; done']) +container = client.containers.run("alpine", ["sh", "-c", 'while true; do echo hello world; sleep 1; done'], detach=True) +print container.id
実行してみる。
~/local/sample $ ./run_container.py 12f106941293c254064d51d414ad2b446522bb7313b3dc27430898865d729c51 ~/local/sample $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 12f106941293 alpine "sh -c 'while true..." 3 seconds ago Up 2 seconds clever_tesla
docker run -d で実行した場合と同様、バックグラウンドでコンテナが起動しました。
List and manage containers
次に、起動済みのコンテナ の ID をリストします。
ファイル名は、list_container.py とします。
#!/usr/bin/env python # -*- coding: utf-8 -*- import docker client = docker.from_env() for container in client.containers.list(): print container.id
実行してみる
~/local/sample $ ./list_container.py 12f106941293c254064d51d414ad2b446522bb7313b3dc27430898865d729c51
さすがに少し味気ないですが、 起動済みコンテナの ID が表示されていますね。
Stop all running containers
次は、起動済みのコンテナを全停止します。
ファイル名は、stop_container.py とします。
#!/usr/bin/env python # -*- coding: utf-8 -*- import docker client = docker.from_env() for container in client.containers.list(): container.stop()
実行してみる
~/local/sample $ docker run -d -p 8080:80 nginx 4709ed26d564e52e41121c9ba98ebc4de07a395a9c262c4ed7b123ac23803927 ~/local/sample $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4709ed26d564 nginx "nginx -g 'daemon ..." 3 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp goofy_bartik ~/local/sample $ ./stop_container.py ~/local/sample $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ~/local/sample $
検証用に起動した、nginx コンテナが stop_container.py の実行により 停止していることが確認できます。
Print the logs of a specific container
次に、コンテナのログを表示します。
先程、作成した list_container.py に少し手を入れます。 以下のコードを実行することにより、全てのコンテナの log が表示されます。
~/local/sample $ git diff ^HEAD diff --git a/list_container.py b/list_container.py index 1e51937..eeead74 100755 --- a/list_container.py +++ b/list_container.py @@ -4,4 +4,4 @@ import docker client = docker.from_env() for container in client.containers.list(): - print container.id + print container.logs() ~/local/sample $
nginx コンテナが起動した状態で、実行してみます。
~/local/sample $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0988e51e1c74 nginx "nginx -g 'daemon ..." About a minute ago Up About a minute 0.0.0.0:8080->80/tcp laughing_heisenberg ~/local/sample $ ./list_container.py 172.17.0.1 - - [15/May/2017:13:35:02 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" "-"
docker logs コマンド同様、コンテナのログが表示されました。
List all images
docker images コマンド同様、コンテナイメージをリストします。 ファイル名は、list_images.py とします。
#!/usr/bin/env python # -*- coding: utf-8 -*- import docker client = docker.from_env() for image in client.images.list(): print image.id
実行してみる。
~/local/sample $ ./list_images.py sha256:02674b9cb179d57c68b526733adf38b458bd31ba0abff0c2bf5ceca5bad72cd9 sha256:3448f27c273f3122fc554d7acf33796efb4df2ad9886efc092c3bfe716e897b7 sha256:6a2f32de169d14e6f8a84538eaa28f2629872d7d4f580a303b296c60db36fbd7 sha256:766ebb052d4f44d2708c5808691644afc0de1263b22cd30464fd85556afb93c3 ~/local/sample $ docker images --all --digests | awk '{print $1 ,"\t",$4, "\t", $3}' REPOSITORY IMAGE DIGEST alpine 02674b9cb179 sha256:c0537ff6a5218ef531ece93d4984efc99bbf3f7497c0a7726c88e2bb7584dc96 nginx 3448f27c273f sha256:12d30ce421ad530494d588f87b2328ddc3cae666e77ea1ae5ac3a6661e52cde6 ubuntu 6a2f32de169d sha256:c2bbf50d276508d73dd865cda7b4ee9b5243f2648647d21e3a471dd3cc4209a0 amazonlinux 766ebb052d4f sha256:7c781c9234e712f135ee402a13ffd5dbf342a9ff1394c73bc5ae4d9b9078e0f8
確かに、イメージID をリストしていますね。
Pull images
次は、イメージを pull します。 ファイル名は、pull_images.py とします。
#!/usr/bin/env python # -*- coding: utf-8 -*- import docker client = docker.from_env() image = client.images.pull("alpine") print image.id
実行してみる。
~/local/sample $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 3448f27c273f 5 days ago 109 MB ubuntu latest 6a2f32de169d 4 weeks ago 117 MB amazonlinux latest 766ebb052d4f 5 weeks ago 162 MB ~/local/sample $ ./pull_images.py sha256:02674b9cb179d57c68b526733adf38b458bd31ba0abff0c2bf5ceca5bad72cd9 ~/local/sample $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine edge e020ea09df00 4 days ago 3.97 MB alpine 3.5 02674b9cb179 4 days ago 3.99 MB alpine latest 02674b9cb179 4 days ago 3.99 MB alpine 3.4 016182cd451a 4 days ago 4.81 MB alpine 3.3 c8ea6694a9aa 4 days ago 4.81 MB alpine 3.2 87ab25c5a2f0 4 days ago 5.26 MB alpine 3.1 765e3ac9a905 4 days ago 5.05 MB nginx latest 3448f27c273f 5 days ago 109 MB ubuntu latest 6a2f32de169d 4 weeks ago 117 MB amazonlinux latest 766ebb052d4f 5 weeks ago 162 MB alpine 2.7 93f518ec2c41 16 months ago 4.71 MB alpine 2.6 e738dfbe7a10 16 months ago 4.5 MB ~/local/sample $
Commit containers
最後に、commit を実行しイメージを作成します。 ファイル名は、commit_containers.py とします。
#!/usr/bin/env python # -*- coding: utf-8 -*- import docker client = docker.from_env() container = client.containers.run("alpine", ["touch", "/helloworld"], detach=True) container.wait() image = container.commit("helloworld") print image.id
公式ドキュメントのソースコードに不備がありましたが、修正されました。(docker/docker.github.io - Pull requests #3267)
実行してみる
~/local/sample $ ./commit_containers.py sha256:ac09116c6e675fded1427d33dccdd43be4ce7276298efa0f6ef983097b7a0a24 ~/local/sample $ docker images | grep hello helloworld latest ac09116c6e67 26 seconds ago 3.99 MB ~/local/sample $ docker run helloworld sh -c 'ls -l /helloworld' -rw-r--r-- 1 root root 0 May 15 14:13 /helloworld
イメージが作成されました。
なお、API の特定バージョンを使用する場合、環境変数 DOCKER_API_VERSION に指定します。 例えば、以下のように Docker API のバージョンを確認し、DOCKER_API_VERSION 環境変数にセットします。
$ docker version $ export DOCKER_API_VERSION='1.27'
Python SDK の詳細については、以下のドキュメントを参照します。
最後に
Python の学習題材として、Docker SDK for Python を選択するのも ありなんじゃないかなと思いました。
ではでは