はじめに
アプリ開発を進めていると、必ずぶつかるのが「データベースのテーブル定義をどう管理するか」という問題です。最初は手作業で CREATE TABLE を流していても、チーム開発になった途端、「誰がどの順番で何を流したのか分からない」という状態に陥ります。
この記事では、シンプルで導入しやすいマイグレーションツール golang-migrate を、Docker 経由で使う方法を初学者向けに解説します。Go の知識は不要です。Docker が動く環境さえあれば誰でも試せます。
そもそもマイグレーションとは
マイグレーションとは、データベースのスキーマ(テーブルやカラムの構造)の変更履歴を、ファイルとしてバージョン管理する仕組みのことです。
たとえば「users テーブルに age カラムを追加する」という変更を SQL ファイルとして保存しておけば、別の開発者やステージング環境でも、同じ手順を再現できます。Git で管理されたファイルを順番に適用していくイメージです。
up と down の考え方
マイグレーションファイルは通常、適用用の up.sql と、巻き戻し用の down.sql の二本セットで作成します。「やり直したい」「一つ前の状態に戻したい」というときに down が使えるため、安全に試行錯誤できます。
golang-migrate の仕組み
golang-migrate は、指定したフォルダ内の SQL ファイルを順番に DB へ適用してくれるツールです。Go 製ですが、公式が Docker イメージを配布しているため、Go をインストールする必要はありません。
ポイントは、マイグレーション用コンテナを毎回使い捨てで起動し、同じ Docker ネットワーク上にある DB コンテナへ接続するという流れです。図にすると次のようになります。
migrate コンテナはローカルの SQL ファイルをマウントして読み込み、ネットワーク越しに DB コンテナへ接続して SQL を流します。実行が終わると --rm オプションにより自動で消えるため、ホスト環境を汚しません。
実際にやってみる
マイグレーションファイルを用意する
プロジェクト直下に db/migrations/ フォルダを作り、命名規則に従って up と down のファイルを置きます。先頭の連番がバージョン番号になります。
db/migrations/
├── 000001_create_users_table.up.sql
└── 000001_create_users_table.down.sql
中身は普通の SQL です。
-- 000001_create_users_table.up.sql
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE
);
-- 000001_create_users_table.down.sql
DROP TABLE users;
DB コンテナを起動する
事前に docker compose で DB を立ち上げておきます。
docker compose up db -d
docker ps
docker ps の NAMES 列に表示される名前(例: sample-app-db-1)が、後ほど接続文字列で使うホスト名になります。同様に docker network ls で _default が付くネットワーク名も控えておきます。
接続テスト
いきなり SQL を流すのではなく、まずは末尾を version にして接続確認だけ行います。
docker run --rm \
--network sample-app_default \
-v "$(pwd)/db/migrations:/migrations" \
migrate/migrate \
-path=/migrations/ \
-database "mysql://appuser:apppass@tcp(sample-app-db-1:3306)/appdb" \
version
error: no migration と表示されれば、接続には成功していて、まだ何も適用されていない正常な状態です。
マイグレーションを実行する
末尾を up に変えるだけで、未適用の SQL がすべて適用されます。
docker run --rm \
--network sample-app_default \
-v "$(pwd)/db/migrations:/migrations" \
migrate/migrate \
-path=/migrations/ \
-database "mysql://appuser:apppass@tcp(sample-app-db-1:3306)/appdb" \
up
適用後にもう一度 version を実行すると、現在のバージョン番号が返ってきます。一つ前に戻したい場合は末尾を down 1 にします。
まとめ
golang-migrate は、SQL ファイルと Docker さえあれば導入できる、非常にとっつきやすいマイグレーションツールです。覚えることは「up と down のファイルを書く」「使い捨てコンテナで適用する」の二つだけ。最初は version で接続確認、慣れてきたら up と down を行き来して、安心して試行錯誤できる開発環境を整えていきましょう。
長いコマンドは Makefile やシェルスクリプトにまとめておくと、チーム内で共有しやすくなります。