PythonからDockerコンテナを起動する。
docker-compose.ymlでも良いのですが・・・
Scrapyの技術同人誌を書いたとき、Dockerの起動はdocker-compose.ymlを書いて起動するようにしました。
kawahara-ci.hatenablog.com
これをPythonのDockerモジュールを使って起動する方法もあるよねと思いました。
pip install docker
をやってから早速やってみました。
コンテナの状態
プログラムからDockerのコンテナを起動するとき、コンテナは3つの状態が考えられます。
- 該当のコンテナが起動済み。
- 該当のコンテナがあるが起動してない。
- 該当コンテナが存在しない。
この3つの状態を理解して作っていきましょう。
コンテナが起動済み
docker.from_env()
でDockerのオブジェクトを取得しておき、そのオブジェクトから、コンテナリスト(containers.list()
)を調べて、コンテナ名と一致していたら、コンテナが起動しているので、何もしないで終わります。
コンテナがあるが起動してない
コンテナリスト(containers.list()
)のデフォルトは起動しているコンテナを取得しますが、パラメータにall=True
を追加するとすべての状態のコンテナリストを取得します。
最初に起動しているかを確認しているので、このときに取得できたコンテナリストとコンテナ名が一致したら、起動していないコンテナがあることになります。
そのときはcontainer.restart()
でコンテナを再起動します。
コンテナが存在しない
最後は、コンテナが存在しない状態なのでcontainers.run
でDockerイメージをpullしてコンテナを起動してしまいます。
なお、Dockerイメージが既にpull済みのときは、コンテナの起動だけをします。
containers.run('scrapinghub/splash', name='splash', ports={'8050/tcp': 8050}, detach=True)
このような感じでコンテナを起動します。
ここで重要なのはname
パラメータです。
コンテナを起動するとき名前を設定しないと、Dockerは良きに計らえということで適当な名前を付けてしまいます。
そうなると、コンテナの存在を確認しにくいので、コンテナの名前を付けて起動するようにします。
完成形
以上のことを踏まえて作ると、以下のようになります。
3つの状態を判別してコンテナが起動できるようになりました。
import sys import docker container_name = 'splash' client = docker.from_env() container_exists = False for container in client.containers.list(): if container_name == container.name: container_exists = True print('Container is up.') if container_exists == False: for container in client.containers.list(all=True): if container_name == container.name: container.restart() print('Container restartup.') sys.exit() container = client.containers.run('scrapinghub/splash', name=container_name, ports={'8050/tcp': 8050}, detach=True) print('Container startup.')