Compose を始めましょう

このページにおいて Docker Compose 上で動く簡単な Python ウェブ・アプリケーションを作り出していきましょう。このアプリケーションは Flask フレームワークを使うもので、Redis を使ってアクセスカウンタを管理します。このサンプルでは Python を用いていますが、たとえ Python に詳しくない方でも、ここに示す考え方は十分に理解できるようになっています。

必要条件

Docker EngineDocker Compose がインストール済であること。Python と Redis はインストールしておく必要はなく、いずれも Docker イメージによって提供されます。

ステップ1:セットアップ

アプリケーションの依存関係を定義します。

  1. プロジェクト用のディレクトリを作成します。
$ mkdir composetest
$ cd composetest
  1. プロジェクト用のディレクトリに移動し、好みのエディタで app.py という名称のファイルを作成します。
from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello World! I have been seen {} times.\n'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

この例において redis とはアプリケーションネットワーク上にある redis コンテナのホスト名です。Redis のポートとしてデフォルトの 6379 を利用します。

  1. プロジェクト用のディレクトリで、もう一つ requirements.txt という名称のファイルを作成し、次のようにします。
flask
redis

ステップ2:Dockerfile の作成

このステップでは、Docker イメージを構築する Dockerfile を作ります。そのイメージには依存するすべてもの、つまり Python と Python アプリケーションが含まれます。

プロジェクト用のディレクトリ内で、Dockerfile という名称のファイルを作成し、次の内容にします。

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

これは Docker に対して以下の指示を行います。

  • Python 3.4 イメージを使って、イメージを構築する
  • カレントディレクトリ . を、イメージ内のパス /code に加える
  • 作業用ディレクトリを /code に指定する
  • Python の依存パッケージをインストールする
  • コンテナに対するデフォルトのコマンドを python app.py にする

Dockerfile の書き方の詳細については、 Docker ユーザ・ガイドDockerfile リファレンス をご覧ください。

ステップ3:Compose ファイル内でのサービス定義

プロジェクト用のディレクトリに移動し、docker-compose.yml という名称のファイルを作成し、次の内容にします。

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

この Compose ファイルは webredis という2つのサービスを定義します。web サービスは次のように設定します。

  • カレントディレクトリにある Dockerfile から構築されるイメージを利用します。
  • コンテナの公開用ポート 5000 を、ホストマシンのポート 5000 にポートフォワードします。Flask ウェブ・サーバに対するデフォルトポート 5000 をそのまま使います。

redis サービスは、Docker Hub レジストリから取得した Redis イメージを利用します。

ステップ4:Compose によるアプリケーションの構築と実行

  1. プロジェクト用のディレクトリで docker-compose up を実行しアプリケーションを起動します。
$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
redis_1  | 1:C 17 Aug 22:11:10.480 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 17 Aug 22:11:10.480 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 17 Aug 22:11:10.480 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
web_1    |  * Restarting with stat
redis_1  | 1:M 17 Aug 22:11:10.483 * Running mode=standalone, port=6379.
redis_1  | 1:M 17 Aug 22:11:10.483 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
web_1    |  * Debugger is active!
redis_1  | 1:M 17 Aug 22:11:10.483 # Server initialized
redis_1  | 1:M 17 Aug 22:11:10.483 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
web_1    |  * Debugger PIN: 330-787-903
redis_1  | 1:M 17 Aug 22:11:10.483 * Ready to accept connections

Compose は Redis イメージを取得し、コードに基づいたイメージを構築します。そして定義したサービスを開始します。この例では、イメージの構築時にコードが静的にコピーされます。

  1. ブラウザで http://0.0.0.0:5000/ を開き、アプリケーションが動いていることを確認します。

Linux、Docker for Mac、Docker for Windows において Docker を直接使っている場合は、ウェブアプリは Docker デーモンが動くホスト上のポート 5000 をリッスンして受けつけます。ブラウザから http://localhost:5000 を入力すると、Hello World メッセージが表示されるはずです。表示されない場合は http://0.0.0.0:5000 を試してください。

Mac や Windows 上で Docker Machine を使っている場合は、 docker-machine ip 仮想マシン名 を実行すると、Docker ホストの IP アドレスを取得できます。そこでブラウザから http://仮想マシンのIP:5000 を開きます。

ブラウザには以下のメッセージが表示されます。

Hello World! I have been seen 1 times.
../_images/quick-hello-world-1.png
  1. このページを再読み込みします。

数字が増えます。

Hello World! I have been seen 2 times.
../_images/quick-hello-world-2.png
  1. 別のターミナルウィンドウを開いて、docker image ls と入力し、ローカルイメージの一覧を表示してみます。

この時点におけるイメージの一覧は redisweb になります。

$ docker image ls
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
composetest_web         latest              e2c21aa48cc1        4 minutes ago       93.8MB
python                  3.4-alpine          84e6077c7ab6        7 days ago          82.5MB
redis                   alpine              9d8fa9aa0e5b        3 weeks ago         27.5MB

docker inspect <tag または id> によってイメージを確認することもできます。

  1. アプリケーションを停止させます。2つめに開いたターミナルウィンドウ上のプロジェクトディレクトリにおいて docker-compose down を実行します。別のやり方として、アプリを開始したはじめのターミナルウィンドウ上において CTRL+C を入力します。

ステップ5:Compose ファイルにバインドマウントを追加

プロジェクトディレクトリ内にある docker-compose.yml を編集して、web サービスへの バインドマウント を追加します。

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: "redis:alpine"

新しい volumes というキーは、ホスト上のプロジェクトディレクトリ(カレントディレクトリ)を、コンテナ内にある /code ディレクトリにマウントします。こうすることで、イメージを再構築することなく、実行中のコードを修正できるようになります。

ステップ6:Compose によるアプリの再構築と実行

プロジェクトディレクトリにて docker-compose up を入力する際に、Compose ファイルが更新されていると、アプリは再構築され実行されます。

$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
...

Hello World メッセージをもう一度確認してみます。再読み込みをすると、さらにカウンタが増えているはずです。

重要

共有フォルダ、ボリューム、バインドマウント
  • プロジェクトを Users ディレクトリ(cd ~)以外に置いている場合、利用している Dockerfile やボリュームのドライブやディレクトリは、共有できるようにしておく必要があります。実行時に、アプリケーションファイルが見つからない、ボリュームマウントが拒否される、サービスが起動できない、といったランタイムエラーが発生した場合は、ファイルやドライブを共有にすることを試してください。C:\Users (Windows の場合) または /Users (Mac の場合) 以外のディレクトリにあるプロジェクトに対して、ボリュームマウントは共有するドライブにある必要があります。これはまた、Linux コンテナ を利用する Dock for Windows におけるプロジェクトも同様のことが必要です。詳しくは Dock for Windows における 共有ドライブ や Docker for Mac における ファイル共有 を参照してください。また一般的な利用例に関しては コンテナでデータ管理 を参照してください。
  • 比較的古い Windows OS 上において Oracle VirtualBox を利用している場合は、VB trouble ticket に示されている共有フォルダに関する問題が起こるかもしれません。より新しい Windows システムであれば、Docker for Windows の要件を満たすため、VirtualBox は必要としません。

ステップ7:アプリケーションの更新

アプリケーションのコードは、ボリュームを利用してコンテナ内にマウントされましたから、コードへ変更を行うこと、それを確認することはすぐにできるようになりました。イメージを再構築することは必要ありません。

  1. app.py 内のメッセージを変更して保存します。例えば Hello World! メッセージを Hello from Docker! に変更することにします。
return 'Hello from Docker! I have been seen {} times.\n'.format(count)
  1. ブラウザにてアプリを再読み込みします。メッセージは更新され、カウンタも増加しているはずです。
../_images/quick-hello-world-3.png

ステップ8:その他のコマンドを試す

サービスをバックグラウンドで実行したい場合は、docker-compose up-d フラグ("デタッチ"モード用のフラグ)を付けます。docker-compose ps を実行して、現在動いているものを確認します。

$ docker-compose up -d
Starting composetest_redis_1...
Starting composetest_web_1...

$ docker-compose ps
Name                 Command            State       Ports
-------------------------------------------------------------------
composetest_redis_1   /usr/local/bin/run         Up
composetest_web_1     /bin/sh -c python app.py   Up      5000->5000/tcp

docker-compose run コマンドを使えば、サービスに対してのコマンド実行を行うことができます。たとえば、web サービス上でどのような環境変数が利用可能であるかは、以下のコマンドを実行します。

$ docker-compose run web env

docker-compose --help を実行すれば、その他のコマンドを確認できます。bash や zsh シェルにおいて コマンド補完 をインストールしている場合は、利用可能なコマンドを確認することもできます。

your services once you've finished with them:

docker-compose up -d により Compose を起動し、サービスを停止させたい場合には、以下のコマンドを実行します。

$ docker-compose stop

コンテナも完全に削除し、すべてを終わらせる場合には down コマンドを使います。--volumes を指定すれば、Redis コンテナにおいて利用されているデータボリュームも削除することができます。

ここまで Compose の基本動作について見てきました。

次は何を読みますか