【学習メモ】Dockerを本気で理解しにかかる〜#1-5 docker-composeでコンテナ複数管理〜
概要
こちらの記事の#1-5 です。(#1-2、#1-3、#1-4)
前回までで Dockerfile を使用し、docker run
でコンテナを一つ起動する一通りの流れを見ていきましたので、今回はコンテナを複数管理できる docker-compose について見ていきます。
docker-compose
docker-compose とは yaml 形式で記載されるファイルのことで、コンテナを複数管理することができます。
例えば、一般的な Web アプリケーションでいうと、フロントエンド、バックエンド、DB と 3 つのコンテナが必要となり、一つのアプリケーションを開発するのに毎回 3 回docker run
するのはかなり面倒ですよね。また、通常コンテナはそれぞれ独立した隔離空間となるのでそれぞれのコンテナ間で通信することはできません。
しかし、docker-compose であれば、一つのコマンドで必要な複数のコンテナを起動することができ、各コンテナ間の通信も可能になります。
要するに、docker-compose とは
要は、複数回のdocker run
を一つのファイルで管理できるもの。といったものになります。なので、docker-copose.yml の構文はdocker run
コマンドに対応する形で考えると理解が早くなるかもです。
yaml ファイルとは
時間があれば個別に記事にしてまとめようかと思いますので、ここでは簡単に説明しておきます。
yaml ファイルはインデントで親子関係を表現するファイル形式になっています。
・例
version: "2.4"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
上記は Docker の公式ドキュメントに記載されている例ですが、
- インデントが同じ位置から開始されているものは、並列関係
- ネストされているものは親子関係
-
-
から始まるものはリスト
となっています。
docker-compose.yml の構文
docker-compose 内で使用される構文について、以下でまとめていこうと思います。
version と services
まず docker-compose.yml 絶対必要なものとして version と services があります。
varsion: "3.0"
services:
web:
container_name: "web_service"
db:
container_name: "db_service"
-
version
- docker-compose のファイルのバージョンを指定します。バージョンが違えば構文や機能が違ってきたりしますが、最近は 3.x 系が使用されるのが一般的かと思います。
3.x 系は Docker エンジン 1.13.0 以降で使用可能なようで、詳細はドキュメントを参照してください。
- docker-compose のファイルのバージョンを指定します。バージョンが違えば構文や機能が違ってきたりしますが、最近は 3.x 系が使用されるのが一般的かと思います。
-
services
- こちらには各サービス(コンテナ)の設定を記載していくことになります。上記の例では便宜上、もろもろ省略していますが、service に定義された数だけコンテナが起動されます。
上記では、web と db というサービス(コンテナ)が作成され、各コンテナ名は「web_service」と「db_service」です。
各コンテナ間(サービス間)で通信を行う場合にはサービス名で名前解決ができます。
ただ、一点注意が必要なのは、これはコンテナ内から外部のコンテナに通信する際の話であって、コンテナ外の場合は、db
→localhost
のように置き換えて考える必要があります。 - container_name:上記で簡単に触れましたが、コンテナ名を指定できます。文字列なので、ダブルクォートで囲ってあげてください。
- こちらには各サービス(コンテナ)の設定を記載していくことになります。上記の例では便宜上、もろもろ省略していますが、service に定義された数だけコンテナが起動されます。
image と build
varsion: "3.0"
services:
web:
build: ./php
container_name: "web_service"
ports:
- "80:80"
db:
image: postgres:15.1-alpine
container_name: "db_service"
ports:
- 5432:5432
image と build はどちらもイメージを指定することになります。
違いは以下です。
-
build
指定したディレクトリ直下にある Dockerfile からイメージを作成します。 -
image
DockerHub などの Docker リポジトリからイメージを取得します。
要は使用用途としては、特に独自のカスタマイズが不要なイメージは image で DockerHub からベースイメージを取得。Dockerfile で独自のイメージの設定が必要な場合は、build で Dockerfile のあるディレクトリを相対パスで指定。といった感じになります!
:::note info
※2024/04/27:追記
build と image を両方指定した場合、build で指定されたディレクトリでイメージのビルドが実行され、イメージ名が image で指定された名前として管理されるようです。
:::
port
{外部公開ポート}:{コンテナ内部のポート}
とすることでポートフォワーディングが可能。ポートフォワーディングについては以前まとめたので、概要は省略します。
volumes
{ホストのパス}:{コンテナのパス}
とすることでディレクトリの共有(ボリュームマウント)が可能になります。
enviroment
環境変数を定義することができます。
定義方法は二通りあり、
- key-value 形式
environment:
POSTGRES_USER: db-dev-user
POSTGRES_PASSWORD: password
POSTGRES_DB: dev-db
- リスト形式
environment:
- POSTGRES_USER=db-dev-user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=dev-db
となります。どちらでも大丈夫ですが、リスト形式では、key と value を=
繋ぐことに注意してください。
docker-compose.yml の例
上記を踏まえて、docker-compose.yml を記載すると以下のような感じになりました。
varsion: "3.0"
services:
web:
build: ./php
container_name: "php-container"
ports:
- "80:80"
volumes:
- ./php/html:/usr/share/nginx/html
db:
image: postgres:15.1-alpine
container_name: "db-container"
ports:
- 5432:5432
volumes:
- ./data:/var/lib/postgresql/data
enviroment:
POSTGRES_USER: db-user
POSTGRES_PASSWORD: db-password
POSTGRES_DB: db-name
docker-compose コマンド
まず、以下の docker-compose コマンドは docker-compose.yml が存在するディレクトリで基本的に実行してください。
docker-compose.yml が同階層にない場合は、上位階層を見に行き、見つかったものを実行するようです。
docker-compose up
docker-compose.yml の内容を基に全てのコンテナ起動。-d
オプションをつけてデタッチモードで起動することが多い
docker-compose up -d
docker-compose down
up で起動したコンテナの起動と削除を同時に行ってくれる。
docker-compose restart
docker-compose.yml で管理されているコンテナを全て再起動
docker-compose ps
docker-compose.yml で管理されているコンテナのみ一覧表示
docker-compose run
docker-compose.yml に定義されているサービルの一つを指定してコマンド実行
docker run
vs docker-compose
では、docker-compose
の構文がdocker run
のどのコマンド、オプションに対応するのかを見ていきたいと思います。
機能概要 | docker run | docker-compose |
---|---|---|
イメージ指定 | {イメージ名}:{タグ} |
image or build
|
コンテナ名を指定 |
-n or --name
|
container_name |
ボリュームのマウント |
-v or --volume
|
volumes |
ポートフォワーディング | -p |
ports |
環境変数の定義 |
e or --env
|
enviroment |
主要なものはざっとこんな感じでしょうか。
名前付きボリューム
各サービス配下に定義するvolumes
は上記で記述したですが、volumes
はトップレベルでも記述が可能です。
volumes
をトップレベルで定義した場合、名前付きボリュームを設定することが可能です。
例:
varsion: "3.0"
services:
web:
build: ./php
container_name: "php-container"
ports:
- "80:80"
volumes:
- ./php/html:/usr/share/nginx/html
db:
image: postgres:15.1-alpine
container_name: "db-container"
ports:
- 5432:5432
volumes:
- db-data:/var/lib/postgresql/data
enviroment:
POSTGRES_USER: db-user
POSTGRES_PASSWORD: db-password
POSTGRES_DB: db-name
# 名前付きボリュームの定義を追加
volumes:
db-data:
driver: local
上記の db のvolumes
はdb-data
という名前付きボリュームにマウントしています。
このdb-data
はトップレベルのvolumes
で定義しているものです。この場合、データの保存は Docker 管理下のディレクトリに保存されることになります。
web のサービスで行っているボリュームマウントは今まで通りディレクトリを指定した方法になっています。
これらの使い分けですが、DB のデータのようにホスト側から変更を加えない(もしくは変更してはいけない)ようなデータの永続化は名前付きボリュームで行われるのが一般的です。
それに対して開発中のソースコードはホスト側から変更を加えてリアルタイムに反映したいといったケースがあると思います。この場合にはディレクトリを指定したボリュームマウントが必要となります。
2 種類のボリュームマウント
今までにも説明しましたが、ボリュームのマウントには 2 種類あります。
-
ボリュームマウント:
これが上記の名前付きボリュームでマウントした方式になります。ボリュームマウントの場合は、Docker 管理下のディレクトリにボリュームを確保し、そこに保存されます。
特徴としては、ホスト側から触りにくいといったところでしょうか。そのため、ホスト側から変更する必要がない DB データのボリュームマウントに適しています。 -
バインドマウント:
これが上記のディレクトリを指定したボリュームマウントになります。
特徴はすでにご存知のとおり、ファイルを共有したような感じでホスト側の変更がリアルタイムでコンテナ側に反映されます。
そのため、ホスト側からファイルの変更がしたい、開発中のソースコードなどの場合はバインドマウントが利用されます。
この 2 種類のボリュームマウントについては、大変わかりやすくまとめてくださっている記事があったので、参考にさせていただきました。
まとめ
今回は docker-compose について見ていきました。また、2 種類のボリュームマウントについてもまとめました!
これで一通り開発環境を構築することができるようになったと思いますので、今後の開発ではガンガン使っていこうと思います!
Discussion