Edited at

Flyway で MySQL のバージョン管理をしてみる in docker-compose


背景

デプロイやらローカル環境やらでいくつか不便なことが発生している今日この頃。


  1. アプリをデプロイするたびに、DBの変更差分をSVNのログから目視で探していた。

  2. viewの更新を手作業で実行しており、稀に誤って全tableを初期化する事態が発生していた。

  3. それぞれの環境でどこまでDBの変更が適用されているのかよくわからない。

  4. 作業者の開発環境のDBに差分を適用することが面倒。

  5. デプロイ作業の自動化を進めたい。

といった問題の対応策として flyway を検討してみる。

※ ビルドツールなんてものは存在しない環境なのでプラグインは使えません。

最終的な姿はこちら


構成


  • DB


    • MySQL 8.0.15




  • Flyway


    • Flyway Community Edition 5.2.4 by Boxfuse



  • 最終的なDirectory構成


sample-flyway

│ docker-compose.yml

├─flyway
│ ├─conf
│ │ flyway.conf
│ └─sql
│ V0.000__Baseline.sql
│ V1.001__Create_table_test.sql
│ V1.002__Insert_table_test.sql
│ V2.001__Create_person_table.sql
└─mysql
└─initdb.d
schema.sql


DBの準備

まずは MySQL 単体で動作確認する。


docker-compose.yml

version: '3.4'

services:
mysqldb:
image: mysql:8.0
environment:
MYSQL_DATABASE: sample_db
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: pass


起動して接続できることを確認する。

[sample-flyway]$ docker-compose up -d mysqldb

Creating network "sampleflyway_default" with the default driver
Creating sampleflyway_mysqldb_1 ... done

[sample-flyway]$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------
sampleflyway_mysqldb_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp

[sample-flyway]$ docker-compose exec mysqldb mysql -u root -p -e 'show databases;'
Enter password:
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sample_db |
| sys |
+--------------------+

DBが動くことを確認。


Flywayの準備

docker-compose.ymlflyway の記述を追加する。


docker-compose.yml

version: '3.4'

services:
mysqldb:
image: mysql:8.0
environment:
MYSQL_DATABASE: sample_db
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: pass
# === ココカラ ===
migratedb:
image: boxfuse/flyway:latest
volumes:
- ./flyway/sql:/flyway/sql
- ./flyway/conf:/flyway/conf
depends_on:
- mysqldb
command: migrate
# === ココマデ ===


設定ファイルを用意する。


flyway.conf

flyway.url=jdbc:mysql://mysqldb:3306/sample_db

flyway.user=root
flyway.password=pass

差分のSQLを用意する。


V1.001__Create_table_test.sql

CREATE TABLE v1_difference_application (id INT);



V1.002__Insert_table_test.sql

INSERT INTO v1_difference_application VALUES(100);

INSERT INTO v1_difference_application VALUES(101);


V2.001__Create_person_table.sql

CREATE TABLE person (id INT NOT NULL, name VARCHAR(100) NOT NULL);


マイグレーションしてみる。

[sample-flyway]$ docker-compose run --rm migratedb

Starting sampleflyway_mysqldb_1 ... done
Flyway Community Edition 5.2.4 by Boxfuse
Successfully validated 3 migrations (execution time 00:00.039s)
Creating Schema History table: `sample_db`.`flyway_schema_history`
Current version of schema `sample_db`: << Empty Schema >>
Migrating schema `sample_db` to version 1.001 - Create table test
Migrating schema `sample_db` to version 1.002 - Insert table test
Migrating schema `sample_db` to version 2.001 - Create person table
Successfully applied 3 migrations to schema `sample_db` (execution time 00:00.358s)

成功した。DBを確認する。

[sample-flyway]$ docker-compose exec mysqldb mysql -u root -p -D sample_db -e 'select * from v1_difference_application;'

Enter password:
+------+
| id |
+------+
| 100 |
| 101 |
+------+

マイグレーションできた。よかった。

docker-compose down で停止しておく。


新規作成以外の場合はどうする?

既存システムの場合は既にテーブルやデータが作られてしまっているので、上記手順では「既にデータベースが作られてるよ」と言われマイグレーションできない。

そのため、ベースラインとして既にある構造の分を設定することで、そこからの差分を管理してもらうことができる。

docker-compose up -d mysqldb でDBを起動しておく。

既存DBのSQLを追加


V0.000__Baseline.sql

CREATE TABLE init_table (id INT);


migratedb サービスの commandinfo で上書きして初期状態を確認する。

[sample-flyway]$ docker-compose run --rm migratedb info

Starting sampleflyway_mysqldb_1 ... done
Flyway Community Edition 5.2.4 by Boxfuse
Schema version: << Empty Schema >>

+-----------+---------+---------------------+------+--------------+---------+
| Category | Version | Description | Type | Installed On | State |
+-----------+---------+---------------------+------+--------------+---------+
| Versioned | 0.000 | Baseline | SQL | | Pending |
| Versioned | 1.001 | Create table test | SQL | | Pending |
| Versioned | 1.002 | Insert table test | SQL | | Pending |
| Versioned | 2.001 | Create person table | SQL | | Pending |
+-----------+---------+---------------------+------+--------------+---------+

StatePending になっている。

ベースラインを設定してみる。

[sample-flyway]$ docker-compose run --rm migratedb baseline -baselineVersion=0_000 -baselineDescription=Baseline

Starting sampleflyway_mysqldb_1 ... done
Flyway Community Edition 5.2.4 by Boxfuse
Creating Schema History table: `sample_db`.`flyway_schema_history`
Successfully baselined schema with version: 0.000

[sample-flyway]$ docker-compose run --rm migratedb info
Starting sampleflyway_mysqldb_1 ... done
Flyway Community Edition 5.2.4 by Boxfuse
Schema version: 0.000

+-----------+---------+---------------------+----------+---------------------+----------+
| Category | Version | Description | Type | Installed On | State |
+-----------+---------+---------------------+----------+---------------------+----------+
| | 0.000 | Baseline | BASELINE | 2019-03-26 06:57:18 | Baseline |
| Versioned | 1.001 | Create table test | SQL | | Pending |
| Versioned | 1.002 | Insert table test | SQL | | Pending |
| Versioned | 2.001 | Create person table | SQL | | Pending |
+-----------+---------+---------------------+----------+---------------------+----------+

Baseline が設定できた。

マイグレートしてみる。

[sample-flyway]$ docker-compose run --rm migratedb

Starting sampleflyway_mysqldb_1 ... done
Flyway Community Edition 5.2.4 by Boxfuse
Successfully validated 4 migrations (execution time 00:00.065s)
Current version of schema `sample_db`: 0.000
Migrating schema `sample_db` to version 1.001 - Create table test
Migrating schema `sample_db` to version 1.002 - Insert table test
Migrating schema `sample_db` to version 2.001 - Create person table
Successfully applied 3 migrations to schema `sample_db` (execution time 00:00.241s)

[sample-flyway]$ docker-compose run --rm migratedb info
Starting sampleflyway_mysqldb_1 ... done
Flyway Community Edition 5.2.4 by Boxfuse
Schema version: 2.001

+-----------+---------+---------------------+----------+---------------------+----------+
| Category | Version | Description | Type | Installed On | State |
+-----------+---------+---------------------+----------+---------------------+----------+
| | 0.000 | Baseline | BASELINE | 2019-03-26 06:57:18 | Baseline |
| Versioned | 1.001 | Create table test | SQL | 2019-03-26 06:57:59 | Success |
| Versioned | 1.002 | Insert table test | SQL | 2019-03-26 06:57:59 | Success |
| Versioned | 2.001 | Create person table | SQL | 2019-03-26 06:57:59 | Success |
+-----------+---------+---------------------+----------+---------------------+----------+

StateSuccess になった。よかった。


+alpha


  1. k8sの初期化コンテナにするとか

  2. CI/CDツールでコミット検知して自動マイグレーションするとか

してみると楽しいかもしれない。