Docker Compose を使う¶
Docker Compose とは、複数コンテナのアプリケーションを定義・共有するために役立つように、開発されたツールです。Compose があれば、サービスを定義する YAML ファイルを作成し、コマンドを1つ実行するだけで、瞬時にすべて立ち上げたり、すべてを削除したりできます。
Compose を使う「大きな」利点は、アプリケーション スタックをファイルに定義し、プロジェクト用リポジトリの一番上に置けるため(これでバージョン管理できます)、プロジェクトに貢献しようとしている誰もが簡単に利用できます。誰もが必要なのは、リポジトリを複製(クローン)し、それから
それでは、どのようにして使い始めるのでしょうか?
Docker Compose のインストール¶
Docker Desktop for Window や Mac や Linux をインストール済みであれば、Docker Compose が入っています! Play-wih-Docker インスタンスも、同様に Docker Compose がインストール済みです。
Docker Engine を単体でインストールした場合は、別のパッケージとして Docker Compose のインストールが必要です。 Compose プラグインのインストール を御覧ください。
インストール後は、以下のように実行できるようになり、バージョン情報が表示されます。
$ docker compose version
Compose ファイルの作成¶
/getting-started/app
フォルダのルートでdocker-compose.yml
という名前のファイルを作成します。
compose ファイル内では、アプリケーションの一部として実行したいサービス(あるいはコンテナ)の一覧の定義から始めます。
services:
それでは、 compose ファイルへ、サービスを一気に移行しましょう。
アプリのサービス定義¶
覚えていますか、以下はアプリ用コンテナの定義に使ったコマンドです。
$ docker run -dp 127.0.0.1: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:18-alpine \
sh -c "yarn install && yarn run dev"
まずはじめに、サービスを記述し、コンテナ用のイメージを定義しましょう。サービスには様々な名前を選べます。この名前が、自動的にネットワーク エイリアス(別名)となり、MySQL サービスの定義時に役立ちます。
services: app: image: node:18-alpine
通常、
image
定義の近くにcommand
がありますが、順番は無関係です。それでは、ファイルを先へと進めましょう。services: app: image: node:18-alpine command: sh -c "yarn install && yarn run dev"
コマンドの
-p 127.0.0.1:3000:3000
を移行するには、サービス用のports
を定義しましょう。ここでは 短い構文 を使いますが、より細かな 長い構文 も同様に使えます。services: app: image: node:18-alpine command: sh -c "yarn install && yarn run dev" ports: - 127.0.0.1:3000:3000
次に、作業ディレクトリ(
-w /app
)とボリュームの割り当て (-v "$(pwd):/app"
)の両方を移行するため、working_dir
とvolumes
定義を使います。ボリュームも 短い構文 と 長い構文 があります。Docker Compose でボリューム定義を使う利点の1つは、現在のディレクトリからの相対パスが使える点です。
services: app: image: node:18-alpine command: sh -c "yarn install && yarn run dev" ports: - 127.0.0.1:3000:3000 working_dir: /app volumes: - ./:/app
最後は、
environment
キーを使って環境変数の定義を移行する必要があります。services: app: image: node:18-alpine command: sh -c "yarn install && yarn run dev" ports: - 127.0.0.1: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:8.0
まず新しいサービスと、その名前を
mysql
と定義すると、ネットワーク エイリアスも自動的に得られます。次に進み、使用するイメージも同様に定義します。services: app: # The app service definition mysql: image: mysql:8.0
次に、ボリューム
割り当て を定義します。docker run
でコンテナを実行した時は、名前付きボリューム が自動的に作成されました。ですが、 Compose の実行時には、そのようになりません。トップレベルのvolume:
セクションでボリュームを定義する必要があり、さらに、サービス設定でもマウントポイントの指定が必要です。単にボリューム名だけを指定すると、デフォルトのオプションが使われます。他にも更に多くの利用可能なオプション があります。services: app: # The app service definition mysql: image: mysql:8.0 volumes: - todo-mysql-data:/var/lib/mysql volumes: todo-mysql-data:
さいごに、環境変数のみを指定する必要があります。
services: app: # The app service definition mysql: image: mysql:8.0 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data:
これで、 docker-compose.yml
の全体は、このようになっているでしょう。
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 127.0.0.1:3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
アプリケーション スタックの実行¶
ようやく docker-compose.yml
ファイルの準備ができましたので、これで起動できます!
まず、app や 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: '8.0.31' 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
)。
これでアプリが開けるようになり、実行中だと分かります。そして、どうでしょう! たった1つのコマンドでできました!
Docker ダッシュボードでアプリのスタックを表示¶
Docker ダッシュボードを見ますと、 app という名前のグループが見えます。これは Docker Compose による「プロジェクト名」で、同じグループのコンテナに対して使われます。デフォルトでは、プロジェクト名はシンプルに docker-compose.yaml
が置かれているディレクトリ名です。
app の▶マークをクリックして展開しますと、compose ファイルで定義した2つのコンテナが見えます。コンテナ名も説明的になり、 <サービス名>-<レプリカ数>
のパターンに従います。そのため、どのコンテナがアプリで、どのコンテナが mysql データベースなのかを、素早く見つけるのが簡単になります。
全てを削除¶
すべてを解体(終了および削除)する準備が調えば、シンプルに docker compose down
を実行するか、Docker ダッシュボード上でアプリ全体のゴミ箱をクリックします。コンテナは停止され、ネットワークも削除されます。
警告
ボリュームの削除
デフォルトでは、compose ファイルの名前付きボリュームは docker compose down
の実行では削除「されません」。ボリュームも削除したい場合は、 --volumes
フラグも追加する必要があります。
Docker ダッシュボードでは、アプリのスタックを削除してもボリュームは削除「されません」。
解体が終われば、他のプロジェクトに切り替えができ、 docker compose up
を実行したら、そのプロジェクトに貢献する準備が調います! これ以上、本当にシンプルなことはありません!