情けないながら苦戦してしまいました。
整理のために、謎の技術集団zeneloアドベントカレンダーの16日担当として記しておきます。
何がしたいのか?
Dockerコンテナで動かしているアプリケーションから、他のDockerコンテナで動いているmysqlにアクセスしたい。
I want to connect mysql in a docker container from another container.
というわけです。(英語でググる人にも引っかかるように書いておく。)
コードはよ
せっかちさんのためにコードを先に書いておきます。
version: "2"
services:
mysql:
container_name: sample-mysql
image: mysql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_DATABASE: 'sample-mysql-db'
MYSQL_USER: "root"
restart: 'always'
expose:
- '3306'
ports:
- "3306:3306"
networks:
- app-net
app:
container_name: "sample-application"
build:
context: "./"
dockerfile: "Dockerfile"
networks:
- app-net
networks:
app-net:
driver: bridge
こちらはアプリケーションのDockerfile。
今回はmysqlにつなぎたいだけなので、mysql-clientだけインストールします。
FROM alpine:latest
RUN apk update && \
apk add mysql-client
動作確認
$ docker-compose build
// mysqlだけ先に起動しておく
$ docker-compose run -d mysql
// appコンテナの中に入る
$ docker-compose run app sh
$ mysql -h sample-mysql -u root -D sample-mysql-db -p
=> つなげた!
解説していきます。
コンテナ間の通信設定にはネットワーク機能を使う
いくらdocker-composeで一緒にコンテナを起動しようとも、 ネットワークの設定なしではコンテナ間の通信はできません。
詳しいことは公式ドキュメントを読んでいただきたいですが、今回は ブリッジネットワーク
を使って、アプリケーションコンテナとmysqlコンテナを通信可能にします。
networks:
app-net:
driver: bridge
ちょうどこの部分です。
これにより、 app-net という新しいネットワーク空間を定義できました。
そうしたら、
services:
mysql:
networks:
- app-net
app:
networks:
- app-net
このように書くことで、コンテナがどこのネットワークに属すのかを記述することができます。
あとは、アプリケーション側のコンテナに入り、mysqlに接続します。
$ mysql -h sample-mysql -u root -D sample-mysql-db -p
このとき重要なのは -h localhostではない点です。
コンテナ間の通信は コンテナ名をIPの代わりに指定する 必要があります。
(これに気づかず、かなり躓いていました。)
すごいざっくりな記事になってしまい恐縮ですが、コンテナ間の通信に困っている人は、とりあえずこの記事で繋げるようにしてもらって、あとは公式ドキュメントを読み漁り理解を深めてください!では!