JVM系のマイグレーションツールの導入
新しくSpring Bootの開発環境をコンテナ上で作る上で、DBマイグレーションツールのMyBatis Migrationsをコンテナで使えるようしたので、その手順をまとめておきます。
Docker Composeの構成
作っていた開発環境のマイグレーション関連部分に絞ってディレクトリ構成を表すと、以下のようになっています。
$ tree -d
.
├── sample
│ └── migration
│ ├── drivers
│ └── sample
│ ├── environments
│ └── scripts
└── mysql
├── conf.d
├── data
├── log
├── sql
└── tmp
└── data
プロジェクトルートにdocker-compose.ymlを置き、それ起因でコンテナを運用するようにしています。
マイグレーション自体はdocker composeを持つリポジトリとは別で管理しているので、 アプリケーション名のディレクトリ(ここではsample)配下に、migrationディレクトリとしてgit cloneして利用するイメージです。
- docker-compose.yml
version: '3.7' services: migration: build: context: ./sample/migration/ image: sample-migration container_name: sample_migration command: /bin/bash tty: true working_dir: "/sample/migration" volumes: - ./sample/migration:/sample/migration:cached depends_on: - db db: image: mysql:8 container_name: sample_db environment: MYSQL_ROOT_PASSWORD: "root" #MYSQL_DATABASE: "sample" MYSQL_USER: "admin" MYSQL_PASSWORD: "admin" volumes: - ./mysql/sql:/docker-entrypoint-initdb.d - ./mysql/conf.d:/etc/mysql/conf.d - ./mysql/data:/var/lib/mysql - ./mysql/tmp/data:/tmp/data - ./mysql/log:/var/log/mysql command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ports: - "3306:3306"
このdocker-compose.ymlでは、MySQL 8のコンテナを立ち上げ、その後マイグレーション用のコンテナを立ち上げています。
MySQLのコンテナイメージ
MySQLのコンテナイメージでは、MYSQL_DATABASEを指定することで、予めDBを作成することもできるのですが、 DBは複数利用することを考え、コンテナイメージ作成時に実行されるinit.sqlで作成するようにしています。
CREATE DATABASE sample CHARACTER SET utf8mb4; GRANT ALL ON *.* TO 'admin'@'%' WITH GRANT OPTION; CREATE USER 'admin'@'localhost' IDENTIFIED BY 'admin'; CREATE USER 'admin'@'127.0.0.1' IDENTIFIED BY 'admin'; FLUSH PRIVILEGES;
MyBatis Migrationsのコンテナイメージ
本題のMyBatis Migrationsのコンテナイメージは、OpenJDKのイメージをベースに作成します。
- sample/migration/Dockerfile
FROM openjdk:11-slim
RUN apt-get update && apt-get install -y \
wget \
unzip \
&& apt-get clean \
&& rm -rf /var/lib/apt
RUN wget https://github.com/mybatis/migrations/releases/download/mybatis-migrations-3.3.5/mybatis-migrations-3.3.5-bundle.zip \
&& unzip mybatis-migrations-3.3.5-bundle.zip -d /usr/local \
&& rm mybatis-migrations-3.3.5-bundle.zip
ENV MYBATIS_MIGRATIONS_HOME /usr/local/mybatis-migrations-3.3.5
ENV PATH $PATH:$MYBATIS_MIGRATIONS_HOME/bin
WORKDIR /sample/migration
COPY . .
CMD ["/bin/bash"]
docker-compose up -d
後(コンテナイメージ起動後)、コンテナに入ってマイグレーションスクリプトのテンプレートを作成します。
mkdir sample cd sample migrate init
この際、コマンド実行ディレクトリにdriversディレクトリが作成されますが、複数DBのスクリプト管理をすることを考え、WORKDIR配下にdriversを移動させます。
実際に利用するMySQLのJDBCコネクタは、以下からダウンロードし、先ほどのディレクトリに配置してください。
その後、プロパティの以下を生成された値から変更します。
- time_zoneをAsia/Tokyoに
- script_char_setをアンコメント
- JDBCに必要な設定を追加(driverのクラスに注意)
- send_full_scriptをアンコメントしてfalseに
sample/migration/sample/environments/development.properties
## Base time zone to ensure times are consistent across machines time_zone=Asia/Tokyo ## The character set that scripts are encoded with script_char_set=UTF-8 ## JDBC connection properties. driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://db:3306/sample username=admin password=admin # # A NOTE ON STORED PROCEDURES AND DELIMITERS # # Stored procedures and functions commonly have nested delimiters # that conflict with the schema migration parsing. If you tend # to use procs, functions, triggers or anything that could create # this situation, then you may want to experiment with # send_full_script=true (preferred), or if you can't use # send_full_script, then you may have to resort to a full # line delimiter such as "GO" or "/" or "!RUN!". # # Also play with the autocommit settings, as some drivers # or databases don't support creating procs, functions or # even tables in a transaction, and others require it. # # This ignores the line delimiters and # simply sends the entire script at once. # Use with JDBC drivers that can accept large # blocks of delimited text at once. send_full_script=false # This controls how statements are delimited. # By default statements are delimited by an # end of line semicolon. Some databases may # (e.g. MS SQL Server) may require a full line # delimiter such as GO. # These are ignored if send_full_script is true. delimiter=; full_line_delimiter=false # If set to true, each statement is isolated # in its own transaction. Otherwise the entire # script is executed in one transaction. # Few databases should need this set to true, # but some do. auto_commit=false # If set to false, warnings from the database will interrupt migrations. ignore_warnings=true # Custom driver path to allow you to centralize your driver files # Default requires the drivers to be in the drivers directory of your # initialized migration directory (created with "migrate init") driver_path=/sample/migration/drivers # Name of the table that tracks changes to the database changelog=CHANGELOG # Migrations support variable substitutions in the form of ${variable} # in the migration scripts. All of the above properties will be ignored though, # with the exception of changelog. # Example: The following would be referenced in a migration file as ${ip_address} # ip_address=192.168.0.1
これで準備完了です。
使い方
実際に利用する際は、initしたときのように起動後にコンテナ内に入ってmigrate up
を実行でもいいですが、以下のように直接実行することもできます。
$ docker-compose up -d $ docker-compose exec migration bash -c "cd sample && migrate up"
初回の起動スクリプトなどを組む場合は、こちらの使い方が便利です。
手順は以上です。よいコンテナライフを!