はじめに
ECS 上でのマイグレーション管理について、さまざまな方法を試して比較する機会があったため、整理することにしました。
どの方法が適しているかは環境や運用方針によって異なるため、それぞれのメリット・デメリットを明確にしておきたいと考えました。
このまとめが、自分自身の備忘録としてだけでなく、同じ課題に直面する方の参考になればと思います。
1. Go アプリの main.go でマイグレーション
メリット
- シンプルで管理しやすい。
-
main.goにマイグレーション処理を組み込むだけでOK。 - 追加の設定が不要で、すぐに実装可能。
デメリット
- アプリが起動するたびにマイグレーションが実行される。
- アプリがクラッシュすると、マイグレーションの途中で止まる可能性がある。
- コンテナをスケールアウトすると、複数のコンテナが同時にマイグレーションを実行する可能性がある。
実装例 (main.go にマイグレーションを追加)
package main
import (
"log"
"skill-typing-back/db"
"skill-typing-back/model"
)
func main() {
dbConn := db.NewDB()
if dbConn == nil {
log.Fatal("データベースの初期化に失敗しました")
}
log.Println("マイグレーションを実行中...")
err := dbConn.AutoMigrate(
&model.User{},
&model.Category{},
&model.Question{},
&model.Answer{},
&model.Choice{},
&model.Score{},
)
if err != nil {
log.Fatal("マイグレーションに失敗しました: ", err)
}
log.Println("マイグレーション完了")
// アプリの通常の処理に進む
}
2. ECS の migrate コンテナを使う
メリット
- 本番環境に最適。マイグレーション完了後にアプリが起動するよう制御可能 (
dependsOnを使用)。 - マイグレーションの管理が分離される。アプリとマイグレーションの実行タイミングを分けられる。
- Terraform でインフラをコード化できる。
デメリット
-
Terraformの設定が少し増える。 - マイグレーション用のコンテナを別途作成する必要がある。
Terraform の migrate タスク定義例
resource "aws_ecs_task_definition" "migrate" {
family = "my-app-migrate"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = "256"
memory = "512"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
task_role_arn = aws_iam_role.ecs_task_execution_role.arn
container_definitions = jsonencode([
{
"name": "migrate",
"image": "my-ecr-repo:latest",
"command": ["/migrate"],
"essential": true,
"networkMode": "awsvpc"
}
])
}
ECS の migrate コンテナを手動実行する方法
aws ecs run-task --cluster my-ecs-cluster \
--task-definition my-app-migrate \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-xxxxx],securityGroups=[sg-xxxxx],assignPublicIp=ENABLED}"
3. aws ecs execute-command で手動実行
メリット
- 簡単に試せる。
- 追加の
migrateコンテナやTerraformの設定が不要。
デメリット
- 自動化されない。毎回手動で実行する必要がある。
- 複数環境での管理が難しい。本番環境での適用ミスが起こる可能性がある。
マイグレーションを実行するコマンド
aws ecs execute-command --cluster my-ecs-cluster \
--task <TASK_ID> \
--container app \
--command "/migrate"
まとめ: どの方法を選ぶべきか?
| 方法 | メリット | デメリット |
|---|---|---|
Go の main.go でマイグレーション |
シンプルで管理しやすい | アプリが起動するたびにマイグレーションが実行される |
ECS の migrate コンテナを使う |
マイグレーション後にアプリ起動 (dependsOn) |
Terraform の設定が少し増える |
手動で aws ecs execute-command を実行 |
簡単に試せる | 自動化されない |
最適な選択肢
- 本番環境なら →
ECS の migrate コンテナを作成して、自動化 - 開発環境なら →
aws ecs execute-commandで手動実行 - シンプルにしたいなら →
Go の main.go でマイグレーションを組み込む
プロジェクトの要件に応じて適切な方法を選択していきたいと思いました。