この記事はZOZO Advent Calendar 2024 シリーズ6 18日目の記事になります。
はじめに
sqldef
について調べたので、データベーススキーマをマイグレーションする方法をまとめてみました。
sqldefとは
sqldef
は、データベースのスキーマを定義ファイルに基づいて自動的に更新するツールです。MySQL、PostgreSQL、SQLiteなど複数のデータベースをサポートしており、手動でスキーマを変更する手間を省き、バージョン管理されたスキーマ定義を簡単に適用できます。
プロジェクトのセットアップ
以下のコマンドでプロジェクトディレクトリと必要なサブディレクトリを作成します。
# プロジェクトディレクトリを作成
mkdir sqldef-example
cd sqldef-example
# 必要なディレクトリを作成
mkdir -p docker/sqldef database
Dockerfile
の作成
docker/sqldef/Dockerfile
を以下の内容で作成します。
Dockerfileではsqldef
とdockerize
をインストールし、エントリーポイントスクリプトを設定します。
# ベースイメージとしてAlpine Linuxを使用
FROM alpine
# 作業ディレクトリを設定
WORKDIR /tmp
# 必要なツールをインストール
RUN apk add --update --no-cache curl
# sqldefをダウンロードしてインストール
RUN curl -LO https://github.com/k0kubun/sqldef/releases/download/v0.17.24/mysqldef_linux_amd64.tar.gz && \
tar xvf mysqldef_linux_amd64.tar.gz && \
mv /tmp/mysqldef /usr/bin/mysqldef
# dockerizeをダウンロードしてインストール
RUN curl -L https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-alpine-linux-amd64-v0.6.1.tar.gz -o dockerize-alpine-linux-amd64.tar.gz && \
tar xvf dockerize-alpine-linux-amd64.tar.gz && \
mv /tmp/dockerize /usr/bin/dockerize
# エントリーポイントスクリプトをコピー
COPY docker/sqldef/entrypoint.sh /entrypoint.sh
# エントリーポイントスクリプトに実行権限を付与
RUN chmod +x /entrypoint.sh
# コンテナ起動時に実行するコマンドを設定
ENTRYPOINT ["/entrypoint.sh"]
スキーマ定義ファイルの作成
database/create_tables.sql
を以下の内容で作成します。
データベースに適用するスキーマ定義を記載します。
-- usersテーブルを作成
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
エントリーポイントスクリプトの作成
docker/sqldef/entrypoint.sh
を以下の内容で作成します。
このスクリプトはコンテナ起動時に実行され、MySQLが準備完了するのを待ってからsqldef
を実行し、スキーマを適用します。
#!/bin/sh
# MySQLが準備完了するのを待つ
echo "Waiting for MySQL to be ready..."
dockerize -wait tcp://$MYSQL_HOST:$MYSQL_TCP_PORT -timeout 60s
# sqldefを実行してスキーマを適用
echo "Running sqldef..."
mysqldef --user=$MYSQL_USER --password=$MYSQL_PWD --host=$MYSQL_HOST $MYSQL_DATABASE < $SQL_FILE_TO_MIGRATE_APPLICATION_DATABASE
Docker Composeの設定
docker-compose.yml
をプロジェクトのルートディレクトリに以下の内容で作成します。
MySQLとアプリケーションのコンテナを定義し、環境変数を設定します。
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: sqldef-example-db
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- "3306:3306"
app:
build:
context: .
dockerfile: docker/sqldef/Dockerfile
environment:
MYSQL_DATABASE: sqldef-example-db
MYSQL_USER: user
MYSQL_PWD: password
MYSQL_HOST: mysql
MYSQL_TCP_PORT: 3306
SQL_FILE_TO_MIGRATE_APPLICATION_DATABASE: "/mysql/create_tables.sql"
volumes:
- ./database:/mysql
実行
以下のコマンドを実行してコンテナを起動し、マイグレーションを実行します。
docker-compose up
接続確認
以下のコマンドを実行して、MySQLクライアントを使用して接続します。
docker exec -it sqldef-example-mysql-1 mysql -u user -p
パスワードが求められたら、docker-compose.yml
で設定した MYSQL_PASSWORD
(password
) を入力します。
接続後、以下のコマンドを実行します。
SHOW DATABASES;
USE sqldef-example-db;
SHOW TABLES;
DESCRIBE users;
users
テーブルが表示されれば、接続とスキーマの作成が成功しています。
これで、sqldef
を使用したデータベーススキーマのマイグレーションが実行され、動作確認まで完了しました。