はじめに
業務の中で、ローカル環境で様々検証するために、あるコンテナから別のコンテナで立ち上げたMySQLのDBに対して接続をする必要が出てきました。
かなり苦戦してしまったので、その方法について備忘のためにまとめておきます。
概要
今回私がやろうとしていた対応の概要は以下のとおりです。
プロジェクトA
アプリ用コンテナ、MySQL用コンテナの2つのコンテナを持つ。
プロジェクトB
アプリ用コンテナを持つ。プロジェクトAのMySQL用コンテナに接続したい。
どちらのアプリ用コンテナもNode.js、Express、TypeScipt、Prismaを使用しています。
また、Docker Composeのバージョンは3.5以上であることを想定しています。
対応方法
端的にいうと、接続される側と接続する側、双方のコンテナで同じネットワークを使用するようにする、ということになります。
詳細な設定方法を確認します。
接続される側
DBのコンテナを持つ側は2つの対応が必要です。
以下はそのコード例です。
version: '3.8'
services:
# アプリ用コンテナ定義
app:
build: .
ports:
- "3000:3000"
# 〜中略〜
networks:
- external-mysql
# DB用コンテナ定義
db:
image: mysql:8.0
ports:
- "3306:3306"
# 〜中略〜
networks:
- external-mysql
networks:
external-mysql:
name: external-mysql # 明示的に名前をつける
docker-compose.yml
ファイルに対して大きく2つの対応を行っています。
まずはトップレベルのnetworks
の定義です。
networks:
external-mysql:
name: external-mysql
これを定義することで、ネットワークが作成されます。
2行目のexternal-mysql
はDocker Compose内でこのネットワークを参照するための名前です。
3行目のname: external-mysql
はDocker上で実際に作成されるネットワークの名前です。
※name
が指定できるのはバージョンが3.5以上になります。
name
を指定しない場合、2行目に指定した``external-mysql`に対して、プロジェクト名がプレフィックスとして付与されるため、名前が一定になりません。
次に、サービスレベルのnetworks
の定義です。
networks:
- external-mysql
どちらも名前がnetworks
なのでややこしいですが、こちらはapp
とdb
の各サービスに対して設定します。
これはどのネットワークを使用するかの設定になります。
接続される側の設定は以上です。
接続する側
接続する側も同じように、トップレベルとサービスレベルのnetworks
の定義が必要になります。
version: '3.8'
services:
app2:
build: .
ports:
- "3001:3000"
environment:
- DATABASE_URL=mysql://user:password@db:3306/myapp
# 〜中略〜
networks:
- external-mysql
networks:
external-mysql:
external: true
name: external-mysql # 既存のネットワークに接続
サービスレベルのnetworks
は先ほどと変わらないので割愛します。
トップレベルのnetworks
には先ほどなかった
external: true
の記載が増えています。
これは、外部のネットワークを使用する、つまりこのプロジェクトのDockerCompose外のネットワークを使用するという宣言になります。
これにより、接続される側で設定したネットワークを使用することができます。
また、networks
以外の設定ポイントとして、DB接続情報があります。
environment:
- DATABASE_URL=mysql://user:password@db:3306/myapp
@
以降はホスト名:ポート名
となりますが、ここではホスト名として、接続される側のdocker-compose.yml
のservices
で指定したDBのサービス名であるdb
を使用しています。
まとめ
普段Dockerは触り慣れていないので、設定するのにかなり苦労しました。
同じような悩みにぶち当たっている人の一助となれば幸いです。