MongoDBをgolang-migrate/migrateでマイグレーションしてみる
2024/02/12 / 2024/02/12
golang-migrate/migrateを使ってMongoDBをマイグレーションする試みです。
Dockerでローカル環境作るところも含めて説明します。
ページの最後に、全体のコードをアップロードしたGitHubのリンクを載せておきます。
背景
MongoDBのマイグレーションライブラリは私が調べたところ、2つしかありませんでした。
xakep666/mongo-migrateはREADME.mdをすぐ使い方が分かりました。
しかし、golang-migrate/migrateは分かりにくかったと感じました。
そのため、本記事を作成した次第です。
どちらを使うか迷っている方の参考になればと思っています。
バージョン
利用したバージョンは以下です。
| 環境 | バージョン |
|---|---|
| MongoDB | 7.0.5 |
| golang-migrate/migrate | 4.17.0 |
レプリカセットのキーを作成
レプリカ間で安全に情報をやりとりするために暗号化キーを用意します。
以下のコマンドを実行してください。
$ openssl rand -base64 756 > replicaset.key
$ chmod 600 replicaset.key
$ chown 999 replicaset.key
docker-compose.ymlを用意
今回は以下のようなdocker-compose.ymlファイルを用意しました。
最新のMongoDBのバージョンは公式サイトから確認できます。
version: "3.9"
x-commons: &commons
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
MONGO_INITDB_DATABASE: testdb
image: mongo:7.0.5
command: mongod --replSet rs0 --keyFile /etc/replicaset.key
services:
mongodb-primary:
container_name: go_migrate_mongo_primary
<<: *commons
ports:
- "27017:27017"
volumes:
- ./replicaset.key:/etc/replicaset.key
- go_migrate_mongo_primary_data:/data/db
mongo-secondary:
container_name: go_migrate_mongo_secondary
<<: *commons
ports:
- "27018:27017"
volumes:
- ./replicaset.key:/etc/replicaset.key
- go_migrate_mongo_secondary_data:/data/db
mongo-tertiary:
container_name: go_migrate_mongo_tertiary
<<: *commons
ports:
- "27019:27017"
volumes:
- ./replicaset.key:/etc/replicaset.key
- go_migrate_mongo_tertiary_data:/data/db
mongo-arbiter:
container_name: go_migrate_mongo_arbiter
<<: *commons
ports:
- "27020:27017"
volumes:
- ./replicaset.key:/etc/replicaset.key
- go_migrate_mongo_arbiter_data:/data/db
## Docker上でhttps://github.com/golang-migrate/migrateを実行するためのコンテナ
## https://hub.docker.com/r/migrate/migrate
migrate:
container_name: migrate
image: migrate/migrate:latest
entrypoint: sh
tty: true
volumes:
- .:/var/task
working_dir: /var/task
command: ""
volumes:
go_migrate_mongo_primary_data:
go_migrate_mongo_secondary_data:
go_migrate_mongo_tertiary_data:
go_migrate_mongo_arbiter_data:
docker-compose up -dで実行します。
イニシャライズ
MongoDBはデータベースを立ち上げた後、手動で初期化する必要があります。
まずは、primaryのmongoshを開いてください。
docker exec -it go_migrate_mongo_primary bash
mongosh -u root -p root
次に、レプリカセットの初期化を実行します。
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "go_migrate_mongo_primary:27017", priority: 3 },
{ _id: 1, host: "go_migrate_mongo_secondary:27017", priority: 2 },
{ _id: 2, host: "go_migrate_mongo_tertiary:27017", priority: 1 },
{ _id: 3, host: "go_migrate_mongo_arbiter:27017", arbiterOnly: true },
],
})
rs.status()やrs.conf()を使って、初期化がうまく行ったか確認することができます。
マイグレーションファイルを用意
公式ライブラリがサンプルのマイグレーションファイルを用意してくれています。
これを拝借しましょう。
バージョンダウン用のdown.jsonとバージョンアップ用のup.jsonが必要です。migrations/001_create_user.down.jsonを作成してください。
[
{
"dropUser": "deminem"
}
]
migrations/001_create_user.up.jsonを作成してください。
[
{
"createUser": "deminem",
"pwd": "gogo",
"roles": [
{
"role": "readWrite",
"db": "testMigration"
}
]
}
]
ちなみに、migrate create -ext json -dir ./migrations -seq {ファイル名}を使うことでテンプレートファイルを作成することができます。
マイグレーション
バージョンをアップさせるときは以下のコマンドを実行してください。
migrate -path ./migrations -database "mongodb://root:root@localhost:27017/testdb?authSource=admin&directConnection=true" up 1
バージョンダウンするときは以下です。
migrate -path ./migrations -database "mongodb://root:root@localhost:27017/testdb?authSource=admin&directConnection=true" down 1
ときどきdirty状態になることがあります。その際は以下のコマンドを実行しましょう。
migrate -path ./migrations -database "mongodb://localhost:27017/testdb?directConnection=true" force 1
注意点
migrate/database/mongodb/README.mdによれば、以下のように書かれています。
mongodb://user:password@host:port/dbname?query(mongodb+srv://also works, but behaves a bit differently. See docs for more information)
言い換えると、MongoDB Atlasで利用すると挙動が少し変化するため注意が必要のようです。
全体のコード
全体のコードはこちらです。
GitHub – taako-502/go-migrate-sample: …
GitHub – taako-502/go-migrate-sample: …
MongoDB migrations using golang-migrate/migrate library – taako-502/go-migrate-sample
MongoDB migrations using golang-migrate/migrate library – taako-502/go-migrate-sample
まとめ
個人的にはあまりおすすめできないと思いました。
xakep666/mongo-migrateのほうが良さそうです。
- MongoDBのバージョン4.2までしかテストされていない
- MongoDBに限定すると最終コミットが2年前
- go.mongodb.org/mongo-driveのバージョンが古い
- 時々Dirtyモードになる
- Atlasの挙動がローカルと異なる
- MongoDB以外のデータベースに対応している分、コード量が多く影響範囲がわかりにくい
一方、xakep666/mongo-migrateも似ていて、あまりメンテがされていないのですが、こちらはコード量が非常に少なくシンプルであるため、その気になれば自分でフォークしてメンテできるというのが利点だと思いました。
また、xakep666/mongo-migrateはMongoDBに特化しているので、無駄なコードもなく読みやすいです。
参考
golang-migrateでMongoDBマイグレーションやってみた
golang-migrateでMongoDBマイグレーションやってみた