Dockerを使って複数のコンテナを動かして動作するアプリのことを「マルチコンテナアプリケーション」と呼びます。
今までは、「マルチコンテナアプリケーション」を構築するには、前回の記事のように手動で使用するコンテナに対してコマンドを実行する必要がありました。
しかしコンテナが増えてくるとそれぞれの依存関係や起動・再起動の手間がかかります。
そこで開発されたのが、「DockerCompose」になります。
これを使うことで、1つのファイルに複数のコンテナの依存関係や実行時の細かい設定などをまとめておけるという利点があります。
また、DockerComposeで起動されるコンテナはすべて実行したDockerCompose用のブリッジネットワークに接続されるので、自動で環境を分離することができるようになっています。
前回の記事では、Dockerfileとコマンドを駆使してコンテナを手動で実行していました。
以下のリンクの前回の記事の面倒くさい手順を見てから、この記事を読むと、よりDockerComposeの利便性が分かりやすいと思います。
まず、DockerComposeを使うには、専用の「docker-compose.yml」を用意する必要があります。
DockerComposeが担うのは、docker container run
などのコンテナを実行する部分がメインなので、独自イメージ
を作るような手順は、Dockerfile
に記述する必要があります。
とりあえずは、「docker-compose.yml」を中身は空でいいので、プロジェクトフォルダの「ルートディレクトリ」に配置してください。
ソースコードの内容は、前回の記事と同じ内容になります。
今回のフォルダ構成は前回の記事と同じような構成ではありますが、「」がルートディレクトリに出ています。
これは、APIサーバーを作成するときにdocker-compose.ymlとDevContaienrを連携させるために外に出しました。
todoApp/
├── docker-compose.yml <- 追加
├── .devcontainer <- 移動
│ └── devcontainer.json <- 移動
├── goApi/
│ ├── Dockerfile
│ ├── go.mod
│ ├── go.sum
│ └── main.go
└── pgdb/
├── Dockerfile
└── init.sql
SQLコンテナ管理をDockerComposeで行う
この節で編集するのは、docker-compose.yaml
だけになります。
それ以外のpgdbフォルダ内にあるファイルは、前回の記事の使いまわしになるので、この記事から読んでいる方は、前回の記事のコードをコピーして使ってください。
まずは、SQLコンテナだけ実行するためのdocker-compose.yml
を記述していきます。
# docker-composeのバージョン
# もう書かなくてもいい気もする
version: '3.9'
services:
# サービス名
pgdb:
# ビルドしたいDockerfileがあるディレクトリを指定
build: ./pgdb
# envファイルのパスを指定
env_file: ./pgdb/.env
# ボリュームのバインド先を指定
volumes:
- db-volume:/var/lib/postgresql/data
# ネットワークのバインド先を指定
networks:
- db-bridge
# ネットワークの作成
networks:
db-bridge:
# ボリュームの作成
volumes:
db-volume:
- version: Docker Composeファイルのバージョンを指定します。
- services: 起動するコンテナをサービスと定義しています。
- pgdb: サービス名(自由に設定可能)。
- build: イメージをビルドする際のビルドコンテキストを指定します。
./pgdb
ディレクトリ内のDockerfile
を使用します。 - env_file: 環境変数を定義したファイルへのパスを指定します。
- volumes: ホストとコンテナ間で共有するボリュームを定義します。
- networks: コンテナが接続するネットワークを指定します。
- build: イメージをビルドする際のビルドコンテキストを指定します。
- pgdb: サービス名(自由に設定可能)。
- networks: ネットワークを定義します。
- db-bridge: ブリッジネットワークの名前です。
- volumes: ボリュームを定義します。
- db-volume: データを永続化するためのボリュームです。
上記のdocker-compose.yml
は、以下のdockerコマンド
を実行したのと同じ意味になります。
# ネットワークの作成
docker network create db-bridge
# ボリュームの作成
docker volume create db-volume
# pgdbサービスのイメージビルド
docker image build -t todoapp_pgdb ./pgdb
# pgdbコンテナの実行
docker container run --name todoapp_pgdb_1 \
--env-file ./pgdb/.env \
-v db-volume:/var/lib/postgresql/data \
--network db-bridge \
-d \
todoapp_pgdb
DockerComposeの実行は、DockerComposeがあるディレクトリに移動して、以下のコマンドを実行するだけですべて実行されます。
# コマンド
docker compose up
# デタッチドモードで実行
docker compose up -d
DockerComposeを使った場合に自動で生成される各構成要素の名前は以下のとおりです。
- イメージ名 :
ルートディレクトリ名-サービス名
になります。- 例 :
todoapp-pgdb
- 例 :
- コンテナ名 :
{ルートディレクトリ名}-{サービス名}-{数字}
になります。- 例 :
todoapp-pgdb-1
- 例 :
- ネットワーク名 :
{ルートディレクトリ名}_{ブリッジネットワーク名}
- 例 :
todoapp_db-bridge
- 例 :
- ボリューム名 :
{ルートディレクトリ名}_{ボリューム名}
- 例 :
todoapp_db-volume
- 例 :
止めたい場合は、以下のコマンドを実行するだけで「コンテナの停止」「コンテナの削除」、「生成したネットワークの削除」、などの後片付けをしてくれます。
Volumeは永続化するための領域なのため自動で削除されません。
削除したい場合は、手動で削除する必要があります。
docker compose down
前回の記事ではAPIサーバーの開発のためにDevContainerを使っていたのですが、DockerComposeを使いながらDevContaienrを使う方法をご紹介します。
前提として、DockerComposeからDevContainerを起動することはできません。
しかし、DevContaierからDockerComposeを起動することはできるのでその方法を使おうと考えています。
DevContainerでdocker-compose.yaml
の設定を使ってDockerComposeで各コンテナを起動して、指定したコンテナにDevContainerで接続するという方法です。
buildでDockerfileを対象にしてコンテナを生成していたところを、dockerComposeFile、serviceに変更して、DockerComposeをベースにコンテナに接続するように変更しています。
{
"name": "Go DevContainer",
"dockerComposeFile": "../docker-compose.yml",
"service": "goapi",
"workspaceFolder": "/workspace/goApi",
"customizations": {
"vscode": {
"extensions": [
"golang.go"
]
}
}
}
- dockerComposeFile : docker-compose.ymlまだのパスを指定します。
- service : DevContainerをつなげたいサービス業を指定します。
既存のFROMはそのままで、コンテナ実行時にtailコマンドを実行して、コンテナがすぐに終了しないようにします。
最初にDockerComposeが動いてからDevContainerで接続するまでの間でコンテナが止まってしまうためです。
FROM golang:1.23.2
CMD ["tail", "-f", "/dev/null"]
version: '3.9'
services:
pgdb:
build:
context: ./pgdb
dockerfile: Dockerfile
env_file:
- ./pgdb/.env
volumes:
- db-volume:/var/lib/postgresql/data
networks:
- db-bridge
goapi:
build:
context: ./goApi
dockerfile: Dockerfile
# ポートをバインド
ports:
- "8080:8080"
# バインドマウントは相対を使える
volumes:
- ./goApi:/workspace/goApi
networks:
- db-bridge
# データベースコンテナが先に起動しておいてほしい
depends_on:
- pgdb
networks:
db-bridge:
volumes:
db-volume:
docker-compose.ymlの中であれば、バインドマウントを使う場合の縛りであった絶対パス
出ないといけないという縛りを解除する事ができて、相対パス
を使うことができる
以下の記事をもとに、.devcontaienrフォルダのあるディレクトリをVSCodeで開いてDevContainerで接続すればデータベースコンテナも自動で起動してくれます。
当然データベースへの接続も、DevContainer実行時に
停止する場合も実行時と同じようにDevContainer
の接続を切ると停止できます。
しばらく開発をしない場合は、docker compose down
も実行しておくと、きれいな状態で終わらせることができます。