Docker Compose の利用
読む時間の目安: 6 分
Docker Compose は、複数コンテナーによるアプリケーションを定義しやすく共有しやすくする目的で開発されたツールです。 この Compose を使う場合には、YAML ファイルを生成してそこにサービス定義を行い、ただ 1 つのコマンドだけですべてを結び合わせたり切り離したりすることができます。
Compose を利用する 最大 の利点は、アプリケーション全体の定義を 1 つのファイルに収められることです。 そのファイルはプロジェクトリポジトリのトップに置きます(ここからはバージョン管理していくことにします)。 Compose を使えば他の人がプロジェクトに参加しやすくなります。 他の人はただリポジトリをクローンするだけで Compose アプリを起動します。 現在 GitHub/GitLab 上にある実に多くのプロジェクトが、まさにそのようにして作業を進めています。
ではどうやってはじめましょうか。
Docker Compose のインストール🔗
Windows または Mac 上において Docker Desktop/Toolbox をインストールしていれば、すでに Docker Compose もインストールされています。 Play-with-Docker インスタンスにも Docker Compose がインストールされています。 Linux マシンを利用している方は Docker Compose のインストール が必要です。
インストール後は以下のコマンドを実行すれば、バージョン情報を確認できます。
$ docker-compose version
Compose ファイルの生成🔗
-
アプリプロジェクトのルートディレクトリに
docker-compose.yml
という名前のファイルを生成します。 -
Compose ファイルではまずスキーマバージョンの定義から書き始めます。 たいていはサポートされている最新バージョンを利用します。 Compose ファイルリファレンス を見れば、最新のスキーマバージョンや互換性マトリックスを確認できます。
version: "3.7"
-
次にアプリケーションを構成するサービス(つまりコンテナー)一覧を定義します。
version: "3.7" services:
そこでサービスを一気に Compose ファイルに書き加えていきます。
アプリサービスの定義🔗
思い出してください。 以下のコマンドはアプリコンテナーの定義を以前行ったものです。
$ docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"
PowerShell を利用している場合は以下のコマンドでした。
PS> docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
--network todo-app `
-e MYSQL_HOST=mysql `
-e MYSQL_USER=root `
-e MYSQL_PASSWORD=secret `
-e MYSQL_DB=todos `
node:12-alpine `
sh -c "yarn install && yarn run dev"
-
まずサービス定義の項目とコンテナーイメージを記述します。 サービス名はどのような名前でもかまいません。 この名前は自動的にネットワークエイリアスとなるため、MySQL サービスを定義する際に利用できます。
version: "3.7" services: app: image: node:12-alpine
-
image
定義のすぐ近くにcommand
があるのが普通です。 ただし記述順はどちらを先にしてもかまいません。 そこでさらにこの先に進みます。version: "3.7" services: app: image: node:12-alpine command: sh -c "yarn install && yarn run dev"
-
-p 3000:3000
というコマンド部分を作ります。 サービスに対するports
を定義するものです。 ここでは 短い文法 で記述することにします。 もちろん 長い文法 で記述することもできます。version: "3.7" services: app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000
-
次はワーキングディレクトリ(
-w /app
)とボリュームマッピング(-v "$(pwd):/app"
)です。 それぞれworking_dir
とvolumes
の定義を行います。 ボリュームにも 短い文法 と 長い文法 があります。Docker Compose におけるボリューム定義の利点は、カレントディレクトリからの相対パスを利用できることです。
version: "3.7" services: app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app
-
最後に環境変数設定を行います。 これには
environment
キーを用います。version: "3.7" services: app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app environment: MYSQL_HOST: mysql MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos
MySQL サーバーの定義🔗
そこでいよいよ MySQL サービスの定義です。 コンテナーにおいてかつて利用したコマンドは以下のものでした。
$ docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
PowerShell を利用している場合は以下のコマンドでした。
PS> docker run -d `
--network todo-app --network-alias mysql `
-v todo-mysql-data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=secret `
-e MYSQL_DATABASE=todos `
mysql:5.7
-
新たなサービスを定義して、これを
mysql
と名づけます。 これによって自動的にネットワークエイリアスが作られます。 そしてこれまでと同様に利用イメージを指定します。version: "3.7" services: app: # The app service definition mysql: image: mysql:5.7
-
次はボリュームマッピングの定義です。
docker run
を実行してコンテナーを起動したときは、名前つきボリュームが自動生成されていました。 しかし Compose を使って起動するときには、そのようにはなりません。 まずボリュームの定義は、最上位項目としてvolumes:
というセクションを設けて、サービス定義の中のマウントポイントをここに指定します。 単純にボリューム名だけを指定すれば、デフォルトのオプションが用いられるようになります。 ただしここには 数多くのオプションが利用可能 です。version: "3.7" services: app: # The app service definition mysql: image: mysql:5.7 volumes: - todo-mysql-data:/var/lib/mysql volumes: todo-mysql-data:
-
最後は必要な環境変数を定義するだけです。
version: "3.7" services: app: # The app service definition mysql: image: mysql:5.7 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data:
ここまでに完成したdocker-compose.yml
は以下のようになります。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
アプリケーションの起動🔗
docker-compose.yml
ファイルができたので実行してみましょう。
-
アプリや DB のコンテナーが他に起動していないことをまず確認します(
docker ps
やdocker rm -f <ids>
)。 -
docker-compose up
コマンドを実行してアプリケーション全体を起動します。 すべてをバックグラウンド実行とするため-d
フラグをつけます。$ docker-compose up -d
実行すると以下のような出力が得られます。
Creating network "app_default" with the default driver Creating volume "app_todo-mysql-data" with default driver Creating app_app_1 ... done Creating app_mysql_1 ... done
ボリュームやネットワークが生成されたことが表示されました。 Docker Compose はデフォルトで、アプリケーションに固有のネットワークを自動的に生成します。 (だからこそ Compose ファイル内ではネットワーク定義を行わなかったのです。)
-
docker-compose logs -f
コマンドを実行してログを確認してみます。 どちらのサービスのログも 1 つにまとめれてログ表示されています。 これは処理タイミングに問題があった場合に、監視を行うのが大変便利になります。-f
フラグはログ出力を「継続する」ものです。 つまりログ発生するたびに順次出力が得られます。コマンドをすでに実行済みであると、以下のような出力となるはずです。
mysql_1 | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections. mysql_1 | Version: '5.7.27' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL) app_1 | Connected to mysql db at host mysql app_1 | Listening on port 3000
ログの各行にはサービス名が(よく色づけされて)表示されます。 これによってメッセージを読み分けることができます。 特定サービスのログを確認したい場合は、ログコマンドの最後にサービス名をつける方法もあります(たとえば
docker-compose logs -f app
)。ヒント: DB 準備を待ったアプリ起動
アプリが起動すると MySQL が起動するまで待ちます。 そしてその後に接続を試みます。 Docker には別のコンテナーが起動、実行、接続可能といった状態になるまで待つようなビルトイン機能はありません。 Node ベースのプロジェクトでは wait-port という依存パッケージを利用することができます。 同じようなプロジェクトは、他のプログラミング言語、他のフレームワーク向けにも存在します。
-
ここまでくれば、アプリを開いて実行確認を行うことができます。 ほら、実行コマンドたった一つで出来上がりです。
Docker ダッシュボードからのアプリ全体の確認🔗
Docker ダッシュボードを見てみると、グループ名として app があります。
これが Docker Compose における「プロジェクト名」であり、コンテナーをとりまとめるために利用されます。
このプロジェクト名はデフォルトでは、単純にdocker-compose.yml
ファイルが存在しているディレクトリ名になります。
app を展開して詳細表示すると、Compose ファイル内で定義した 2 つのコンテナーが表示されます。
そこにつけられている名前にはルールがあります。
それぞれ<project-name>_<service-name>_<replica-number>
というパターンを持っています。
ですからどのコンテナーがアプリであり、どれが MySQL データベースであるかは一目瞭然です。
すべての削除🔗
すべてが不要になったら、単純にdocker-compose down
コマンドを実行します。
あるいは Docker ダッシュボード上であれば、trash can(ゴミ箱)アイコンをクリックします。
コンテナーが停止してネットワークは削除されます。
警告
ボリュームの削除
Compose ファイル内で定めた名前つきボリュームは、
docker-compose down
を実行してもデフォルトでは削除 されません。 ボリュームも削除したいなら--volumes
フラグをつける必要があります。 Docker ダッシュボードではアプリを削除してもボリュームは削除 されません。
すべてを削除したら、今度は別のプロジェクトに切り替えてdocker-compose up
を実行します。
ここからは新たなプロジェクトの開発者です。
何ともはや簡単なこと。
まとめ🔗
本節では Docker Compose を学びました。 これを使ったマルチサービスのアプリケーションなら、極めて簡単にアプリ定義し共有することが可能になります。 Compose ファイルの生成にあたっては、これまで実行してきたコマンドを Compose フォーマットに適するように修正して利用しました。
ここからはチュートリアルをまとめていきます。 もっともイメージビルドに関しては、お伝えしたいベストプラクティスがあります。 Dockerfile を利用していくためには大いなる問題だからです。 この後をご覧ください。
get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop