はじめに
この記事はand factory.inc Advent Calendar 2021の11日目の記事です。
昨日は@ichikawa7ssさんの実機デバッグしたときにクラッシュログを端末から取得するでした。
ごくごく最近にM1 Macを使用することになり、開発で使用しているDockerを動かすべくあれこれしていました。
M1 MacでDockerを動かす際に起こるエラーやその対処、そもそもなんでM1だと動かないの?という話についてはこちらの記事が大変参考になります。
というか参考にしました。とても助かりました、ありがとうございます。
この記事ではそんな環境構築の中、M1に全く関係がないdocker-composeのバグで躓いた話をします。
結論
ググりにくい・ググっても全然解決法が出てこない問題にブチ当たったらとりあえず公式のissueも確認してみた方が良い
何が起きたか
Dockerの構成
Docker Composeを使って以下のような構成のサービスを作っています。
# docker-compose.yml
services:
app:
build:
context: .
dockerfile: ./docker/app/Dockerfile
environment:
- DB_HOST=db
volumes:
- $GOPATH/src:/go/src
command: bash -c "/wait-for-it.sh db:3306"
network_mode: "bridge"
links:
- db
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
volumes:
- ./docker/mysql/init:/docker-entrypoint-initdb.d
- ./docker/mysql/data:/var/lib/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- ./db:/db
network_mode: "bridge"
appコンテナとdbコンテナを連携するような構成で、appで動いているサービスから、dbコンテナで動いているDB(MySQL)内のデータを参照するようになっています。
appコンテナはwait-for-it.shを使ってdbコンテナの起動を待ってから実行されます。
dbコンテナにアクセスできない(というかコンテナ名を使用した通信ができない)
2021/12/04時点で最新版であったDocker Desktop 4.3.0を何も考えずMacに導入し、M1にまつわるいろいろなエラーに対応しながらなんとか各コンテナが立ち上がるところまで持っていけたのですが、サービスを動かしてみるとdbコンテナからデータが取れずエラーになってしまいました。
appコンテナのログを確認すると以下のようなログが出ていました。
wait-for-it.sh: waiting 15 seconds for db:3306
wait-for-it.sh: timeout occurred after waiting 15 seconds for db:3306
2021/12/09 15:29:51 driver: bad connection
docker-compose.yml
内でlinks
を使ってコンテナ名を指定しているので、コンテナ名を使って通信できるようになるはずなのですが、どうもdbコンテナとの連携がうまく行ってない様子…。
疎通確認
M1対応のためにいろいろ設定をいじっていたのでもはや問題が起きてても何が原因なのか分からんと思いつつ、とりあえずDockerコマンドでネットワークを確認してみました。
docker network ls
でネットワークIDを確認し、さらに詳細を確認。
% docker network inspect <ネットワークID>
[
{
"Name": "bridge",
...
"Containers": {
"<appのコンテナID>": {
"Name": "app",
...
"IPv4Address": "172.17.0.6/16",
"IPv6Address": ""
},
"dbのコンテナID": {
"Name": "db",
...
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
},
}
...
]
同じネットワークにはちゃんと入っている。
コンテナに割り振られているIPアドレスが分かったので、とりあえずそのアドレス宛にpingを送ってみると疎通ができました。
% docker exec -it app /bin/bash
root@app# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.192 ms
しかし宛先を「db」に変えるとpingが届かない。
root@app# ping db
/bin/ping: db: Name or service not known
名前解決できてないだと…。
解決
「M1 Macで怪しいエラーを出しながらもコンテナが動いている」という状況だったので、もしかしてその関係で何か起きてるのか…?と怪しんでいたのですが、Name or service not known
を見てどうもDockerの設定がおかしそうだな!?と思ったので解決方法をググってみました。
が、「docker links between containers not working」とかでググっても「MySQLのホストはコンテナ名を指定しないとダメだよ」という記事やlink
という単語が範囲広すぎて全然違う記事が出てきたりして解決に至らない。
(ググって解決しづらかったこと Advent Calendar 2021を見て対応力をつけます。。)
数時間ほど右往左往してたところで以下のissueを発見。
Connecting to wrong database: docker-compose v2 is not respecting links any more - ambiguous "db" hostname
どうやらdocker-compose v2.1.1〜v2.2.1ではlinks
を使用したコンテナ連携がうまく動かないようです。
手元のdocker-composeのバージョンを確認してみると見事にv2.2.1でした。
% docker-compose -v
Docker Compose version v2.2.1
issue内で言及されている通り、Docker Desktopの設定からUse Docker Compose V2
のチェックを外し、各コンテナを再起動したところ、ちゃんとdbコンテナにアクセスできるようになりました。
pingも「db」指定で通る。
root@app# ping db
PING db (172.17.0.3) 56(84) bytes of data.
64 bytes from db (172.17.0.3): icmp_seq=1 ttl=64 time=0.198 ms
最後に
上記issueの人がこの問題をdocker-composeのissueにちゃんと上げてくれていました。
Critical: compose v2.1.1+ loses links affinity for hostname named in links directive
issue内で「links」で検索すると上の方に出てきたので脱力してしまいました…。早くこっちから検索すれば良かった。
すでに修正がマージされているのでdocker-composeのv2.2.2(2021/12/03リリース)では直っているようです。タイムリーなバグにハマってしまった。
そもそもdocker-compose v2.2.1〜2は2021/12/10時点で他のissueでも問題が上がっており、完全に壊れているとまで言われているのでまだ使わない方が良いのかもですね。
何も考えずにDocker Desktopを入れた時にdocker-composeも一緒にインストールされたはずなので、まずその時点からダメだったという感じでもありますが…。
また、今回の対応でlinksオプションはすでに非推奨になっていることを改めて知りました。links
の設定のまま粘らず、これを機にnetworks
オプションに変更して大丈夫かチームメンバに持ちかけたいなと思います。
同じくタイムリーなバグにハマってる人の助けになることを願います。