はじめに
この記事は、Docker-compose.yml
を書いたり、docker-compose
コマンドを使ってアプリケーションを開発したり運用したことがあるが、
——全然わからない、俺は雰囲気で複数コンテナを立ち上げているーー
という方(主に自分)に向けて、あらためてDocker Composeがどういうものかを、簡単に説明した記事です。
この記事のゴール🏁
- なぜ複数コンテナの管理ツールが必要になるのかを把握する
- 複数コンテナ実行管理ツールであるDocker Composeの基礎を理解する
複数コンテナ管理の基礎を学ぶ🐳
1. なぜ複数コンテナの管理ツールが必要になるのか
1.1. 複数コンテナを運用するパターン
現在の一般的な構成である三層アーキテクチャのWebアプリケーションをDockerを使って開発・運用することを例として挙げます。
プロセスとしては、Web・アプリケーション・データベースの3つのプロセスが考えられます。これを1コンテナで実現するのは、(できるにはできるみたいですが)あまり良い構成とは言えません。
スケール・管理がしにくく、プロセスが一つでも落ちるとコンテナが落ちてしまうなど、リスクが高いためです。
なので、現在は1コンテナ=1プロセスとして、それぞれの役割ごとにコンテナを立てるのが一般的になっています。必要に応じてコンテナを追加したり差し替えができるため、スケールや変更が容易になります。
1.2. 管理ツールを使わずに複数コンテナを動かすと...?
ここで、コンテナの起動・管理方法について考えます。1コンテナ=1プロセスなのですから、例えば今回の環境を立ち上げる際には、計3回docker build
& docker run
をすることになります。これは、環境の構成コンテナが増えるごとにコマンドを打つ回数が増えていくことを意味します。また、ポートマッピングの設定など、それぞれのコンテナを起動する際にオプションでいちいち指定しなければなりません。シェルスクリプト化するにしても、コンテナの立ち上げ順序等もあるため、環境の管理は面倒でしょう。
$ docker run --name mysql #この後にvolumesなどのいろいろなオプションがつく
$ docker run --name nginx
$ docker run --name rails
$ #...コンテナの数だけ回数は増える
こうなると、環境を構築するのが面倒になりますし、手動でそれぞれのコンテナを運用することになります。単純に管理・維持が大変になり、"環境構築の手軽さ"というDockerの特徴を潰すことになります。
2. Docker Compose とは🐙
ここで、Docker Composeの登場です。
Docker Compose とは、複数コンテナで構成されるプロジェクトの起動・停止などの手順を、yamlファイルに定義した設定内容に基づいて自動的にしてくれるツールです。
version: '3'
services:
db:
image: postgres:alpine
volumes:
- ./tmp/db:/var/lib/postgresql/data
networks:
- sampleapp
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- ./web/app/
ports:
- '8080:8080'
depends_on:
- db
networks:
- sampleapp
networks:
sampleapp:
external: true
各プロセスのDockerfileを用意した上で、上記のようにdocker-compose.yml
にプロジェクトの設定内容を記述しておき、
$ docker-compose up
とすると、簡単に環境を立ち上げることができます。
2.1. docker-compose.yml で定義する内容
さて、docker-compose.yml
では、どのようなことが設定できるのでしょうか?
Compose ファイル・リファレンスによると、
Compose ファイルは YAML ファイルであり、 サービス(services) 、 ネットワーク(networks) 、 ボリューム(volumes) を定義します。
とあります。
うーん、なんとなく今まで雰囲気でdocker-compose.yml
に書いてきたから、よくわかっていない...(心の声)
ということで、それぞれについてあらためて確認していきたいと思います。
2.1.1. services
servicesには、プロジェクトを構成する各コンテナの情報を定義します。ここには、各コンテナのdocker run
時に指定していたオプションを記述することができます。ポートマッピングの設定や、後述するvolumesやnetworksの設定などもここに記述することで、docker-compose up
でのコンテナ一括起動時に反映してくれるようになります。
2.1.2. volumes
続いて、volumes
に記述する内容です。
起動したコンテナで扱うデータは、コンテナが削除されると一緒に消えてしまいます。また、コンテナを複数起動した際、そのままではお互いのファイルシステムを直接参照できません。
ですが、コンテナには**ボリューム(volume)**と呼ばれる、ディレクトリやファイルをマウントできる領域があり(実体はホスト上に自動生成されるディレクトリ /var/lib/docker/volumes
)、異なるコンテナでも、docker
コマンドのオプションで同じvolumeを指定することで、データの共有が可能になります。
Docker Compose では、その設定も各コンテナ起動時にいちいちオプションをつける代わりに、docker-compose.yml
のvolumes
に定義することで、docker-compose up
でのコンテナ一括起動時に反映してくれるようになります。
2.1.3. networks
最後にnetworks
に定義する内容についてです。
今回の例では、アプリケーションを構成するWeb・アプリケーション・DBの各コンテナを通信させる必要がありました。
ここで、Dockerには、3つの標準ネットワークモデルがあり、設定によってホスト側のネットワークに直接接続したり、コンテナ間を通信させることができます(わかりやすい参考記事)。
特に何も設定せずにコンテナを複数起動させている場合、各コンテナはIPアドレスを指定して通信することは可能ですが、コンテナ名を指定して通信することはできません。コンテナ名で通信させるにはユーザー独自のDockerネットワーク
を設定する必要があります。
その設定も、本来ならdocker network
コマンドでいちいち指定する必要がありますが、Docker Composeではdocker-compose.yml
のnetworks
に定義することで、docker-compose up
でのコンテナ一括起動時に反映してくれるようになります。
まとめ
-
管理ツールを使わずに、複数コンテナ構成プロジェクトを運用しようとすると、各コンテナ実行時にいちいちコマンドを走らせる&オプションで設定する必要があるため、環境構築や環境の維持・再現が大変
-
Docker Composeを使うと、
docker-compose.yml
に各コンテナの情報をまとめて定義しておくことができ、1コマンドで環境が構築できる -
Docker Composeによる管理は、特に
network
やvolume
が複雑な場合に真価を発揮する