背景
デプロイやらローカル環境やらでいくつか不便なことが発生している今日この頃。
- アプリをデプロイするたびに、DBの変更差分をSVNのログから目視で探していた。
- viewの更新を手作業で実行しており、稀に誤って全tableを初期化する事態が発生していた。
- それぞれの環境でどこまでDBの変更が適用されているのかよくわからない。
- 作業者の開発環境のDBに差分を適用することが面倒。
- デプロイ作業の自動化を進めたい。
といった問題の対応策として 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 単体で動作確認する。
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.yml
に flyway
の記述を追加する。
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.url=jdbc:mysql://mysqldb:3306/sample_db
flyway.user=root
flyway.password=pass
差分のSQLを用意する。
CREATE TABLE v1_difference_application (id INT);
INSERT INTO v1_difference_application VALUES(100);
INSERT INTO v1_difference_application VALUES(101);
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を追加
CREATE TABLE init_table (id INT);
migratedb
サービスの command
を info
で上書きして初期状態を確認する。
[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 |
+-----------+---------+---------------------+------+--------------+---------+
State
が Pending
になっている。
ベースラインを設定してみる。
[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 |
+-----------+---------+---------------------+----------+---------------------+----------+
State
が Success
になった。よかった。
+alpha
- k8sの初期化コンテナにするとか
- CI/CDツールでコミット検知して自動マイグレーションするとか
してみると楽しいかもしれない。