この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
golang-migrateとは?
Go言語で作成されたDBマイグレーションツールで、GO言語のライブラリとしてだけではなく、CLIからも利用できます。そのためJavaで開発されているprismatixというサービスでも利用することができます。
JavaのマイグレーションツールにFlywayやliquibaseといったものがあります。その中でこのツールの特徴は、マイグレーションを定義しているファイルをGitHubやAWS S3などから直接参照することができることです。(もちろんローカルのファイルシステムにも対応しています) また対応しているデータベースエンジンも多く、MySQLやPostgreSQL以外にもMongoDBなどにも対応しているなど、様々な場面で使うことができるツールだと思います。
環境構築
今回は手軽に試すためにdocker上で、golang-migrateとPostgreSQLを動作させて検証していきます。
( golang-migrateの公式Docker image 1がありますが、セットアップが難しくないため今回は手動でインストールします。)
1. PostgreSQLのコンテナを起動
% docker run --rm -it -p 5432:5432 -e POSTGRES_PASSWORD=password \
--name postgres postgres
[Note]
- コンテナに名前をつけて起動します
- 引数の環境変数
POSTGRES_PASSWORD
にpostgres
ユーザのパスワードを設定します
2. golang-migrateをインストールするコンテナを起動
以降はこのコンテナの中で作業します。
% docker run --rm -it --link postgres:postgres ubuntu:18.04 bash
[Note]
--link
にPostgreSQLのコンテナ名を指定し、DBにコンテナ内から ホスト名postgres
でアクセスできるようにします
3. golang-migrateをインストール
$ apt-get update && apt-get upgrade -y
$ apt-get install -y curl gnupg2 vim
$ curl -L https://github.com/golang-migrate/migrate/releases/download/v4.11.0/migrate.linux-amd64.tar.gz | tar xvz
$ mv ./migrate.linux-amd64 /usr/bin/migrate
[Note]
- 執筆時点の最新版 v4.11.0 にて以降の検証を行っています
4. 動作確認用のpostgres-clientをインストール
PostgreSQLの公式にインストール手順2がありますので、それに従ってPostgreSQLのクライアントをインストールします。
$ echo 'deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main' > /etc/apt/sources.list.d/pgdg.list
$ curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
$ apt-get update
$ apt-get install -y postgresql-client-12
使ってみよう
golang-migrateをインストールして、公式のPostgreSQLのチュートリアルをやっていきます。
1. example
データベースを作成
PostgreSQLにマイグレーションを行うための example
データベースを作成します。
$ createdb -h postgres -U postgres example
2. マイグレーションのテンプレートを作成
golang-migrate
を使ってマイグレーションファイルのテンプレートを生成します。今回は migrations/example1
ディレクトリに create_users_table
のファイル名で生成します。
$ migrate create -ext sql -dir migrations/example1 -seq create_users_table
/migrations/example1/000001_create_users_table.up.sql
/migrations/example1/000001_create_users_table.down.sql
3. 作成されたテンプレートにそれぞれSQLを記載
作成された2つファイルは、更新用のSQLファイルと切り戻し用のSQLファイルを定義します。
000001_create_users_table.up.sql
に下記を記載します (更新用)
CREATE TABLE IF NOT EXISTS users(
user_id serial PRIMARY KEY,
username VARCHAR (50) UNIQUE NOT NULL,
password VARCHAR (50) NOT NULL,
email VARCHAR (300) UNIQUE NOT NULL
);
000001_create_users_table.down.sql
に下記を記載します (切り戻し用)
DROP TABLE IF EXISTS users;
4. 1回目のマイグレーション実施
golang-migrate
でマイグレーションを行います。
$ export POSTGRESQL_URL='postgres://postgres:password@postgres:5432/example?sslmode=disable'
$ migrate -database ${POSTGRESQL_URL} -path migrations/example1 up
1/u create_users_table (13.397ms)
5. example
にマイグレーションされているか確認
PostgreSQLのクライアントでデータベースに反映されているか確認してみます。
$ psql -h postgres -U postgres example
example=# \d
List of relations
Schema | Name | Type | Owner
-------+-------------------+----------+----------
public | schema_migrations | table | postgres
public | users | table | postgres
public | users_user_id_seq | sequence | postgres
(3 rows)
example=# \d users
Table "public.users"
Column | Type | Collation | Nullable | Default
---------+------------------------+-----------+----------+-------------------
user_id | integer | | not null | nextval('users_user_id_seq'::regclass)
username | character varying(50) | | not null |
password | character varying(50) | | not null |
email | character varying(300) | | not null |
Indexes:
"users_pkey" PRIMARY KEY, btree (user_id)
"users_email_key" UNIQUE CONSTRAINT, btree (email)
"users_username_key" UNIQUE CONSTRAINT, btree (username)
example=# \q
users
テーブルと users_user_id_seq
シーケンスが作成されており、カラムも作成されているので成功しています。
[Note]
schema_migrations
はgolang-migrateが履歴管理などに利用しているテーブルです
6. 2回目のマイグレーションのSQLファイル作成
1回目と同様にテンプレートを作成し、編集を行ってマイグレーションします。
今回はマイグレーション中にトランザクションを使用します。
$ migrate create -ext sql -dir migrations/example1 -seq add_mood_to_users
/migrations/example1/000002_add_mood_to_users.up.sql
/migrations/example1/000002_add_mood_to_users.down.sql
それぞれ編集します。
000002_add_mood_to_users.up.sql
に下記を記載します (更新用)
BEGIN;
CREATE TYPE enum_mood AS ENUM (
'happy',
'sad',
'neutral'
);
ALTER TABLE users ADD COLUMN mood enum_mood;
COMMIT;
000002_add_mood_to_users.down.sql
に下記を記載します (切り戻し用)
BEGIN;
ALTER TABLE users DROP COLUMN mood;
DROP TYPE enum_mood;
COMMIT;
6. 2回目のマイグレーション実施・確認
1回目と同様にマイグレーションを実行し、確認します。
$ migrate -database ${POSTGRESQL_URL} -path migrations/example1 up
2/u add_mood_to_users (9.1277ms)
$ psql -h postgres -U postgres example
example=# \d users
Table "public.users"
Column | Type | Collation | Nullable | Default
---------+------------------------+-----------+----------+-------------------
user_id | integer | | not null | nextval('users_user_id_seq'::regclass)
username | character varying(50) | | not null |
password | character varying(50) | | not null |
email | character varying(300) | | not null |
mood | enum_mood | | |
Indexes:
"users_pkey" PRIMARY KEY, btree (user_id)
"users_email_key" UNIQUE CONSTRAINT, btree (email)
"users_username_key" UNIQUE CONSTRAINT, btree (username)
example=# \q
無事にマイグレーションされていることが確認できました。
[応用編1] GitHubからマイグレーションファイルを取得してみよう
公式のGitHubにはSQLのexample があります。今回はそれを利用させていただき、認証やタグ指定などの確認を行うためにプライベートリポジトリへ次のように作成しました。
ツールに指定するGitHubのURIを変更することで、特定のブランチやタグを取得することができるため試します。
ブランチツリー
* f34fc01 (HEAD -> master, origin/master, origin/HEAD) add new file ($$$$)
| * 735dddc (origin/develop, develop) Add files via upload (#)
|/
* 4ae8484 (tag: v0.2.0) Add files via upload ($$$)
* 23b249b (tag: v0.1.0) Add files via upload ($$)
* 8435828 Add files via upload ($)
* 2eaa8b3 Create README.md
リポジトリ内構造
ファイル名末尾に記載されているの $
#
の記号はブランチツリーの各コミットと対応させてありますので、以降の手順でマイグレーションされているファイルが正しいかの確認にご利用ください。
├── README.md
└── migrations
├── 1085649617_create_users_table.down.sql ($)
├── 1085649617_create_users_table.up.sql ($)
├── 1185749658_add_city_to_users.down.sql ($$)
├── 1185749658_add_city_to_users.up.sql ($$)
├── 1285849751_add_index_on_user_emails.down.sql ($$)
├── 1285849751_add_index_on_user_emails.up.sql ($$)
├── 1385949617_create_books_table.down.sql ($$)
├── 1385949617_create_books_table.up.sql ($$)
├── 1485949617_create_movies_table.down.sql ($$$)
├── 1485949617_create_movies_table.up.sql ($$$)
├── 1585849751_just_a_comment.up.sql ($$$)
├── 1685849751_another_comment.up.sql ($$$)
├── 1785849751_another_comment.up.sql (#)
├── 1885849751_another_comment.up.sql (#)
└── 1900000000_create_sample_table.up.sql ($$$$)
[Note]
- GitHubを利用した場合のURIのフォーマットは githubをご覧ください
URIにブランチなどの指定なしの場合
何も指定しない場合は、masterブランチのHEADが取得されてマイグレーションされていることが確認できます。
$ export POSTGRESQL_URL='postgres://postgres:password@postgres:5432/example?sslmode=disable'
$ export SOURCE_URI='github://your-name:personal-access-token@your-owner/youre-repo/migrations'
$ migrate -database ${POSTGRESQL_URL} -source ${SOURCE_URI} up
1085649617/u create_users_table (15.3183ms)
1185749658/u add_city_to_users (12.8733ms)
1285849751/u add_index_on_user_emails (10.8527ms)
1385949617/u create_books_table (11.0747ms)
1485949617/u create_movies_table (14.886ms)
1585849751/u just_a_comment (11.1459ms)
1685849751/u another_comment (13.8439ms)
1900000000/u create_sample_table (12.2614ms)
URIにDevelopブランチ指定ありの場合
URIに #develop
のようにブランチを指定すると、developブランチが取得されてマイグレーションされていることが確認できます。
$ export POSTGRESQL_URL='postgres://postgres:password@postgres:5432/example?sslmode=disable'
$ export SOURCE_URI='github://your-name:personal-access-token@your-owner/youre-repo/migrations#develop'
$ migrate -database ${POSTGRESQL_URL} -source ${SOURCE_URI} up
1085649617/u create_users_table (15.8906ms)
1185749658/u add_city_to_users (10.8608ms)
1285849751/u add_index_on_user_emails (16.6914ms)
1385949617/u create_books_table (14.0107ms)
1485949617/u create_movies_table (14.2851ms)
1585849751/u just_a_comment (9.2893ms)
1685849751/u another_comment (14.0647ms)
1785849751/u another_comment (12.8647ms)
1885849751/u another_comment (13.949ms)
URIにv0.1.0のタグ指定ありの場合
URIに #v0.1.0
のようにタグを指定すると、タグのリビジョンで取得されてマイグレーションされていることが確認できます。
$ export POSTGRESQL_URL='postgres://postgres:password@postgres:5432/example?sslmode=disable'
$ export SOURCE_URI='github://your-name:personal-access-token@your-owner/youre-repo/migrations#v0.1.0'
$ migrate -database ${POSTGRESQL_URL} -source ${SOURCE_URI} up
1085649617/u create_users_table (9.799ms)
1185749658/u add_city_to_users (13.4742ms)
1285849751/u add_index_on_user_emails (16.0135ms)
1385949617/u create_books_table (8.895ms)
[応用編2] AWS S3からマイグレーションファイルを取得してみよう
1. S3にマイグレーションファイルをアップロード
S3には先ほどと同様に公式のGitHubよりSQLのexampleをアップロードします。ディレクトリ構造はGitHubと同じですので、詳細はそちらを参照してください。
2. S3のアクセス権の設定
S3にアクセスするためユーザには AmazonS3ReadOnlyAccess
ポリシーを付与します。(検証目的以外で利用される場合には、アクセス範囲を絞ることをおすすめいたします)
3. マイグレーションを実行
執筆時点では、S3にアクセスするためのCredentialsの設定方法の記載がありません3が、AWS go sdkを利用しているため以下のように環境変数4に設定します。今回はS3バケットのみ東京リージョンにあるため、リージョンには ap-northeast-1
を指定しています。
$ export AWS_ACCESS_KEY_ID=YOUR_AKID
$ export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
$ export AWS_REGION=ap-northeast-1
マイグレーションファイルが置いてあるS3を指定して実行します。
$ export POSTGRESQL_URL='postgres://postgres:password@postgres:5432/example?sslmode=disable'
$ export SOURCE_URI='s3:///migrations'
$ migrate -database ${POSTGRESQL_URL} -source ${SOURCE_URI} up
1085649617/u create_users_table (14.0349ms)
1185749658/u add_city_to_users (13.6978ms)
1285849751/u add_index_on_user_emails (16.2591ms)
1385949617/u create_books_table (17.9426ms)
1485949617/u create_movies_table (14.4656ms)
1585849751/u just_a_comment (8.4976ms)
1685849751/u another_comment (15.1989ms)
1900000000/u create_sample_table (14.7474ms)
[Note]
- GitHubを利用した場合のURIのフォーマットは aws_s3をご覧ください
[参考] Amazon Aurora (PostgreSQL互換) にマイグレーションしてみよう
以下のようなAmazon Aurora を作成してマイグレーションを行ってみました。
- リージョン: バージニア北部(us-east-1)
- インスタンスサイズ: t3.db.medium
- バージョン: Aurora PostgreSQL (Compatible with PostgreSQL 11.6)
今回は先述のGitHubのリポジトリから develop ブランチを指定し、Auroraにマイグレーションを試してみます。
$ export POSTGRESQL_URL='postgres://postgres:password@database.cluster-xxxxxxxx.us-east-1.rds.amazonaws.com:5432/example?sslmode=disable'
$ export SOURCE_URI='github://your-name:personal-access-token@your-owner/youre-repo/migrations#develop'
$ migrate -database ${POSTGRESQL_URL} -source ${SOURCE_URI} up
1085649617/u create_users_table (2.0493698s)
1185749658/u add_city_to_users (3.8259861s)
1285849751/u add_index_on_user_emails (5.6180448s)
1385949617/u create_books_table (7.4065352s)
1485949617/u create_movies_table (9.2197275s)
1585849751/u just_a_comment (10.9430546s)
1685849751/u another_comment (12.7785849s)
1785849751/u another_comment (14.5836142s)
1885849751/u another_comment (16.3808016s)
今回試したようなSQLでは問題なく動作しておりますが、作者公式サイトではAmazon Aurora (PostgreSQL互換)に対応していると明記しておりません。また使用する際は利用者様の責任においてご利用ください。