開発環境にdocker-composeを使っていて、
テーブルスキーマのマイグレーションをしようとしたらconnection refusedと言われて困った時の対処法です。
結論はマイグレーションをかける側はmysqlが立ち上がるまで待ちましょうという感じです。
(素のSQLでDBがmysqlなら /docker-entrypoint-migrations.d
にSQLを置くでもいいですね。
https://hub.docker.com/r/mathewhall/mysql_migration/
困っていた時に人づてに聞いてこのページにたどり着きました。
そこで wait-for
とか使いましょうという空気感を受け取りました。
成功する場合と失敗する場合を検証してみました。
検証に使ったコードはこのレポジトリにおいてあります。
成功するパターンと失敗するパターンはそれぞれ make success
と make fail
で試せます。
失敗するパターンがこちら
app_1 | 2017/08/16 11:08:24 error: dial tcp 172.26.0.2:3306: getsockopt: connection refused
と出てしまってマイグレーションが走っていません。
$make fail /Applications/Xcode.app/Contents/Developer/usr/bin/make docker/start conf=fail.yml /usr/local/bin/docker-compose -f fail.yml build db uses an image, skipping Building app ... # 中略 app_1 | mv tmp/migrate.linux-amd64 bin/migrate app_1 | make[1]: Leaving directory '/opt/app' app_1 | make migrate/up app_1 | make[1]: Entering directory '/opt/app' app_1 | bin/migrate -path ./migrations -database 'mysql://root:root@tcp(db.local:3306)/test?x-migrations-table=migrate_schema_versions' -verbose up db_1 | 2017-08-16 20:08:24 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). db_1 | 2017-08-16 20:08:24 0 [Note] mysqld (mysqld 5.6.36) starting as process 1 ... app_1 | 2017/08/16 11:08:24 error: dial tcp 172.26.0.2:3306: getsockopt: connection refused app_1 | Makefile:51: recipe for target 'migrate/up' failed app_1 | make[1]: *** [migrate/up] Error 1 app_1 | make[1]: Leaving directory '/opt/app' app_1 | Makefile:17: recipe for target 'start/fail' failed app_1 | make: *** [start/fail] Error 2 app_1 | make: Leaving directory '/opt/app' waitforondockercomposesample_app_1 exited with code 2
成功するパターンがこちら
繋がるまで待って、繋がったらマイグレーションを走らせてくれています。
便利。
app_1 | bin/migrate -path ./migrations -database 'mysql://root:root@tcp(db.local:3306)/test?x-migrations-table=migrate_schema_versions' -verbose up
app_1 | 2017/08/16 11:12:55 Start buffering 1/u AddHogeTable
app_1 | 2017/08/16 11:12:55 Read and execute 1/u AddHogeTable
app_1 | 2017/08/16 11:12:56 Finished 1/u AddHogeTable (read 71.110899ms, ran 227.120362ms)
app_1 | 2017/08/16 11:12:56 Finished after 303.666771ms
app_1 | 2017/08/16 11:12:56 Closing source and database
$make success /Applications/Xcode.app/Contents/Developer/usr/bin/make docker/start conf=success.yml /usr/local/bin/docker-compose -f success.yml build db uses an image, skipping Building app ... # 中略 app_1 | mv tmp/migrate.linux-amd64 bin/migrate app_1 | make[1]: Leaving directory '/opt/app' app_1 | /opt/wait-for db:3306 -- make migrate/up db_1 | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. db_1 | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it. db_1 | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. db_1 | Warning: Using a password on the command line interface can be insecure. db_1 | db_1 | db_1 | MySQL init process done. Ready for start up. db_1 | db_1 | 2017-08-16 20:12:54 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). db_1 | 2017-08-16 20:12:54 0 [Note] mysqld (mysqld 5.6.36) starting as process 1 ... app_1 | make[1]: Entering directory '/opt/app' app_1 | bin/migrate -path ./migrations -database 'mysql://root:root@tcp(db.local:3306)/test?x-migrations-table=migrate_schema_versions' -verbose up app_1 | 2017/08/16 11:12:55 Start buffering 1/u AddHogeTable app_1 | 2017/08/16 11:12:55 Read and execute 1/u AddHogeTable app_1 | 2017/08/16 11:12:56 Finished 1/u AddHogeTable (read 71.110899ms, ran 227.120362ms) app_1 | 2017/08/16 11:12:56 Finished after 303.666771ms app_1 | 2017/08/16 11:12:56 Closing source and database app_1 | make[1]: Leaving directory '/opt/app' app_1 | bash app_1 | make: Leaving directory '/opt/app' waitforondockercomposesample_app_1 exited with code 0
docker-composeで他のコンテナのサービスに対して何かやりたい場合は、
立ち上がりきるまでちゃんと待ってあげないといけないみたいですね。
コンテナ内のサービスが立ち上がるまで待ってくれる便利コマンドを知れてよかったです。
めでたしめでたし。