Renderでマイグレーションだけ実行したい時のプラクティス
背景
RenderでGo + PostgreSQLのアプリケーションを運用する際、マイグレーションだけ実行したいというケースがあります。
たとえば、migrations/migration.go
のようなファイルをRender上で一度だけ走らせたい。しかし、RenderではWorkerサービスを作ると常時稼働扱いで課金対象になるため、単発の処理のためにWorkerを作るのは非効率です。
Herokuユーザー向けに補足
Herkokuだったら、Dynoが2つまで無料です。
マイグレーション用のDynoを作成して、一時的に有効にしてデプロイ後に無効にすれば済んでいました。
同じようなことをRenderでやろうと思ったら、お金がかかると判明しました。
『マイグレーション用のDyno』的な概念は『マイグレーション用のWorkerサービス』に相当します。
一瞬しか使わない『マイグレーション用のWorkerサービス』にWebサービスと同様の課金が発生してしまうというわけですね。。。
最後にちょろっと書いてますが、『CI/CDで外部から叩く』が一番独立性が担保できて良いですけどね。
今回の対応方法は恒久対応としては微妙だが、初期開発とかならありなんじゃないかなと思ってます。
RenderのWorkerサービスは常時課金対象
Renderにおいて、
- Webサービス
- Workerサービス
どちらも常時起動が前提となっており課金対象になります。
Workerはバックグラウンド処理などに使う前提なので、短時間のマイグレーションのために使うのはおすすめできません。
解決策:Webサービスで条件付き実行
一時的にWebサービスとしてマイグレーション処理を実行するという方法があります。
以下のようなコードを main.go
に書いておくことで、環境変数を切り替えるだけでマイグレーションが実行可能です。
func main() {
if os.Getenv("RUN_MIGRATION") == "true" {
runMigrations()
return
}
// 通常のWebサーバ起動
router := setupRouter()
router.Run(":" + os.Getenv("PORT"))
}
Renderの「環境変数」に RUN_MIGRATION=true
を設定してデプロイすれば、
一度だけマイグレーションが走り、アプリケーションは即終了します。
マイグレーション後は変数をOFFにする
その後、Renderの環境変数から RUN_MIGRATION
を削除または false
に戻せば、通常どおりWebアプリとして起動します。
その他の方法
外部からマイグレーションを実行(おすすめ)
- GitHub ActionsなどCI/CDを利用して、RenderのDBに外部から
go run
やpsql
コマンドでアクセス - これにより、Render内に一切Workerやマイグレーション用のサービスを持たずに済む
一時的なWorkerとして即削除(非推奨)
- Workerを作って即削除しても、タイミングによっては課金対象になります
まとめ
方法 | コスト | おすすめ度 |
---|---|---|
WebサービスでRUN_MIGRATION=trueにする | 無料枠内で可 | ◎ 開発初期など限定的に便利 |
Workerを作る | 課金対象になる可能性あり | △ 短期的には非効率 |
CI/CDで外部から叩く | Renderには負担なし | ◎ 安定運用向け |
RenderはシンプルなPaaSなので、こうした小技を活用するとコストと利便性を両立できます。
Discussion