モチベーション
開発環境などでFlywayなどのマイグレーションツールを使うとき、自動でマイグレーションして欲しいですよね。今時の開発環境なら大体DBはローカルでdocker-compose upでシュッと立ち上げる人が多いとおもいます。Flywayもcomposeに登録しておけばFlyway自動で適用できるんじゃね…?となってやってみたんですが、思ったよりハマりどころが多かったのでメモを残します。
MySQL + Flywayの組み合わせでやりましたが、他の組み合わせでも参考になるかもしれません。
基本方針
Flyway公式のdockerイメージを使います。
https://github.com/flyway/flyway-docker
https://hub.docker.com/r/flyway/flyway/
また、DB設定(特にパスワード)は.envに書くようにします。だいたいこんな感じになります。
db:
image: mysql:8.0.30
ports:
- "3306:3306"
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --ngram_token_size=2
healthcheck:
test: MYSQL_PWD=${ENV_MYSQL_PASSWORD} mysql -h127.0.0.1 -P3306 -u... -e "quit"
volumes:
- /var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${ENV_MYSQL_ROOT_PASSWORD}
- MYSQL_PASSWORD=${ENV_MYSQL_PASSWORD}
- MYSQL_DATABASE=...
- MYSQL_USER=...
healthcheck
は後ほど説明します。
つづけてFlywayはこんな感じです。
flyway:
image: flyway/flyway:9.2.1
command: -url=jdbc:mysql://db -schemas=... -user=root -password=${ENV_MYSQL_ROOT_PASSWORD} migrate
volumes:
- ./flyway/sql:/flyway/sql
- ./flyway/drivers:/flyway/drivers
depends_on:
db:
condition: service_healthy
depends_onとDBのURLに先程設定したdbを指定していきます。SQLは./flyway/sqlにおけば、そのファイルを対象にマイグレーションしてくれます。
なぜかConnection failする
実はFlywayのイメージには、MySQLのドライバーが入ってないのか、古いのかわからないですが、うまくMySQLに繋いでくれません。もうちょっとエラーメッセージ分かりやすくしてくれないかな。./flyway/drivers
のようなディレクトリを作り、JDBCドライバーをダウンロードして置き、volumeでマウントするか追加したイメージを作るかすれば動きます。
DB起動中にFlywayが実行されてしまう
DBの起動時にFlywayが実行を試みるものの、DBが起動していないので失敗することがあります。新しいdocker-composeに追加された、依存先にあわせて起動をdelayする機能を使えば、簡単に制御可能です。
今回やりたいのはDBがport待ち受け状態になったらFlywayを実行することなので、health_checkでDBのportを監視しつつ、checkをpassしたら依存するイメージFlywayを実行するようにします。depends_on
を以下のようにします。
depends_on:
db:
condition: service_healthy
conditionに指定できるのは他にもいくつかあります。
これでおそらく動きます。docker-composeで快適な開発ライフを。