Composeとは、複数のコンテナを定義し実行する Dockerアプリケーションのためのツールです。ComposeはYAMLファイルを使い、アプリケーションのサービスを設定します。
本演習では、Composeを使って、3つのサービスから構成されるウェブアプリケーションを定義するcompose.yaml
ファイルを作成し、実行します。対象レベルとしては、Docker Composeについて少し学んだことのある人向けです。本演習を通してComposeの理解を深めていただければと思います。
本記事では、Docker compose v2の使用を想定して記述しています。Docker compose v2では、Docker CLIのコマンドとしてdocker compose
を使用できます。Docker-compose v1をお使いの方は、docker-compose
コマンドを使用してください。互換性があるので問題なく実行できます。※Announcing Compose V2 General Availability
準備
- Dockerのセットアップ(Docker 概要とセットアップ)
- レポジトリ(https://github.com/docker/awesome-compose)のクローン
nginx-flask-mysqlディレクトリを使用します。 - Buildkitの有効化
今回使用するレポジトリには、heredocs構文を使用したDockerfileが含まれます。そのため、Buildkitを有効にする必要があります。最近のバージョンではデフォルトで有効になっています。 - 既にディレクトリ内にcompose.yamlファイルが存在するので、削除するか、名前変更をしてください。
アプリケーションの概要
今回使用するウェブアプリケーション(nginx-flask-mysql)の概要を簡単に紹介します。
pythonを使用して(backend/hello.py
)、MySQLに接続し、テーブルを作成します。そのテーブルに保存した内容をFlaskウェブフレームワークを使用してポート8000で公開、そして、リバースプロキシサーバーとしてnginxを使用して、ポート80番で公開します。
本演習では、Composeファイルに以下3つのサービスを定義します。
db
: MySQLデータベースbackend
:pythonスクリプトproxy
: nginxリバースプロキシサーバー
nginx-flask-mysqlディレクトリの構成としては次のようになっています。
1 2 3 4 5 6 7 8 9 10 11 |
├── backend │ ├── Dockerfile │ ├── hello.py │ └── requirements.txt ├── compose.yaml ├── db │ └── password.txt ├── proxy │ ├── conf │ └── Dockerfile └── README.md |
Composeファイルの作成
以下に示すcompose.yaml
を基に、下記要件を満たすようにComposeファイルを作成してください。進め方を参考にしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
services: db: image: backend: build: proxy: build: volumes: db-data: secrets: db-password: networks: backnet: frontnet: |
要件
Composeファイル内に定義すべきアプリケーションの要件を以下に示します。
db
サービスのDockerイメージはmysql:8
を使用db
サービスにおけるMySQLのrootユーザーのパスワードはdb/password.txt
ファイルを使用db
サービスにおけるMySQLのAuthentication Pluginは、mysql_native_password
を使用
command
を以下のよう定義してください。
1 |
command: '--default-authentication-plugin=mysql_native_password' |
db
サービスに保存されたテーブルデータをdockerボリュームを使用して永続化proxy
サービスのポート番号は、80番をホスト側に公開(backend
サービスのポートはホスト側に公開しない)
※backend
サービスのポートは、開発段階では確認用として、ポート8000番をホスト側に公開してください。ただし、最終的には、proxy
サービスがホスト側に公開するので、backend
サービスのポートをホスト側に公開する必要はありません。- 2つのカスタムネットワーク(
backnet
,frontnet
)を使用db
,backend
間:backnet
backend
,proxy
間:frontnet
※Composeのネットワークについてはこちら(Networking in Compose)を参照ください。
- コンテナが停止すると常に再起動するように設定
- サービスの起動順序は、
db
,backend
,proxy
の順とする。
また、db
サービスにおいて、以下のようなhealthcheck
を定義し、service_healthy
をbackend
サービス起動の条件としてください。
1 2 3 4 5 |
healthcheck: test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --password="$$(cat /run/secrets/db-password)" --silent'] interval: 3s retries: 5 start_period: 30s |
進め方について
上記要件を踏まえて、以下ステップを参考にComposeファイルを作成してみてください。
1. backend
サービス単体を定義し、ホストにポート番号8000で公開
localhost:8000
にアクセスすると、エラーが表示されるはずです。
2. db
サービス単体を定義し、エラーなく起動することを確認
サービスの設定に関しては、
dbbackend/hello.py
を参考にして設定すると良いでしょう。
3. db
サービスとbackend
サービスを起動
にアクセスすると、以下が表示されるばずです。
localhost:8000
1 2 3 4 |
Hello Blog post #1 Hello Blog post #2 Hello Blog post #3 Hello Blog post #4 |
4. proxy
サービスの追加
localhost:80
にアクセスすると、上記と同じものが表示されるはずです。
5. 残りの要件を満たすように設定
Composeファイルの書き方や、docker compose
コマンドについては以下公式ドキュメントのページを参考にしてください。
トラブルシューティング
ログの確認
サービスが正しく起動しない場合は、ログを確認して原因を調査しましょう。以下コマンドが使用できます。
Dockerオブジェクトの情報取得
docker inspect <NAME>
で、Dockerオブジェクト(コンテナ、ネットワーク、ボリュームなど)の情報を見ることができます。例えば、volumeのマウント先や、環境変数の設定などが正しく設定されているのかを確認できます。
ボリュームについて
ボリュームは、コンテナ内の任意のディレクトリやファイルにマウントすることで、コンテナ内のデータを保存し永続化します。このボリュームの性質上、仮に、サービスにエラーが発生した場合も、そのエラー時の間違ったデータがボリュームに保存されます。この状態で、新たにコンテナを作成した場合、この間違ったデータが保存されるボリュームがコンテナ内にマウントされてしまいます。
この状態を避けるために、基本的に開発中は、コンテナ起動前にボリュームを削除することをおすすめします。以下コマンドを使用できます。
docker compose down -v
-v
オプションによりdocker compose up
時に作成されたコンテナ、ネットワークの削除に加えて、ボリュームの削除が可能です。docker volume rm <VOLUME>
アプリケーションの実行
Docker composeコマンドを使用して、アプリケーションを実行してください。
また、以下コマンドにより各サービスの稼動を確認してください。
1 2 3 4 5 6 7 |
$ docker compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------------------- nginx-flask-mysql_backend_1 flask run Up 0.0.0.0:8000->8000/tcp,:::8000->8000/tcp nginx-flask-mysql_db_1 docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp nginx-flask-mysql_proxy_1 nginx -g daemon off; Up 0.0.0.0:80->80/tcp,:::80->80/tcp |
そして、ブラウザで http://localhost:80/ を開き(または、curl localhost:80
)以下のように表示されるかを確認してください。
1 2 3 4 |
Hello Blog post #1 Hello Blog post #2 Hello Blog post #3 Hello Blog post #4 |
チャレンジ問題
上記演習において、Flaskのサーバー機能を使用していました。Flaskのサーバー機能は開発用であり、本番環境向けではないため、WSGIサーバーを使用するのが一般的です。backend
サービスのログにおいても、以下のような警告が表示されているはずです。
- WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
そこで、Python WSGIサーバーであるGunicornライブラリーを使用して、この警告を出ないようにしてください。
まとめ
本演習では、Docker composeを使い、ウェブアプリケーション(nginx-flask-mysql)を定義するcompose.yaml
ファイルを作成し、実行しました。演習を通して、compose.yaml
ファイルの書き方、composeコマンドの使い方を学ぶことが出来たと思います。
今回使用したawesome-composeレポジトリはDockerの公式ドキュメントで紹介されているレポジトリです。多くのDocker composeの例があるので、是非学習に役立ててください。