スキーマ変更をすべてのアプリコンテナの起動時に実行するのではなく、1つの明示的なデプロイ手順として実行すれば、データベースのマイグレーションが重複する問題を防ぎやすくなります。
予防策は、マイグレーションの所有者、認証情報、完了シグナルをそれぞれ1つに集約し、新しいレプリカがトラフィックの処理を開始する前に完了させることです。Webコンテナとワーカーコンテナは、スキーマ変更権限を取得せずに再起動できる状態にし、マイグレーションジョブが正常に完了するまでロールアウトを待機させます。また、旧バージョンと新バージョンのアプリが一時的に共存できるよう、スキーマ変更を設計してください。こうすることで、すべてのレプリカが同じマイグレーション履歴を最初に検出することを期待するだけでなく、競合状態そのものを排除できます。
通常のアプリ起動処理からマイグレーションコマンドを削除する
イメージのエントリーポイント、Composeのコマンド、ワーカーのコマンド、ヘルスチェック用ラッパー、デプロイスクリプトを調べ、自動的にマイグレーションを実行する呼び出しがないか確認します。アプリケーションは、意図的に選択したマイグレーション手順でない限り、スキーマを変更せずに再起動できるようにします。
Octopusのデプロイ記事では、マイグレーションには個別のライフサイクルが必要であり、すべてのマイクロサービスプロセスの起動に結び付けるべきではないと説明しています。
必要な場所ではマイグレーション用バイナリを利用できるようにしておきます。ただし、Webのエントリーポイントと別のジョブの両方から呼び出さないでください。フレームワークのロックに依存する複数の起動経路よりも、明示的な所有者を1つにしたほうが監査しやすくなります。
デプロイ前に1回だけマイグレーションジョブを実行する
リリースに含まれるものと同じマイグレーションファイルを使用するワンショットジョブを作成し、対象データベースが期待されるスキーマ状態に到達した後にのみ正常終了するようにします。アプリケーションのロールアウトは、その結果に依存させてください。
現在のロールアウトガイドでは、すべてのレプリカが起動時に競合するのではなく、1つのジョブをロールアウト前に実行する方法を紹介しています。
マイグレーションタスクをアプリサービスのようにスケールさせないでください。対象データベースごとに1つの実行所有者を設定し、タイムアウト時間、ログ、明確な失敗状態を用意します。新しいアプリバージョンのロールアウトは、失敗状態によってブロックされるようにします。
マイグレーションの成功を条件にアプリケーションを起動する
新しいWebコンテナとワーカーコンテナは、マイグレーションステージが成功を報告するまで待機させます。ただし、待機中の各コンテナがマイグレーション自体を再実行する構成にはしないでください。依存させるのはスキーマ変更の再実行ではなく、その結果です。
Andrew Lockのデプロイパターンでは、マイグレーションロジックを一元化したまま、アプリのPodがマイグレーションを待機します。
小規模なホームサーバースタックでは、専用のComposeサービスと制御されたデプロイスクリプトを使って同じ原則を実装できます。マイグレーションに失敗した場合、ロールアウトが明確に停止するほどシンプルな仕組みにしてください。
重複期間中も後方互換性のあるスキーマ変更を使用する
ローリングデプロイでは、旧バージョンと新バージョンのアプリケーションが一時的に同じデータベースへ接続することがあります。旧バージョンがまだ使用しているフィールドを、旧バージョンの停止前に削除または名前変更するマイグレーションは避けてください。
最近のゼロダウンタイムマイグレーションガイドでは、破壊的なクリーンアップの前に追加的なスキーマ変更を適用できるよう、縮小する前に拡張することを推奨しています。
必要に応じて、大規模な変更を拡張、バックフィル、切り替え、縮小のフェーズに分割します。旧レプリカがリクエストを処理している間に、新しいコンテナだけが理解できるスキーマをマイグレーションジョブで作成しないでください。
アプリのレプリカからマイグレーション用認証情報を分離する
可能であれば、スキーマ変更権限を持つデータベースアカウントは、ワンショットのマイグレーションステージだけで使用します。通常のアプリコンテナには、アプリケーションデータに必要な読み取り権限と書き込み権限だけを付与してください。
Liquibaseのデプロイ記事では、データベース変更は自動化に組み込むべきであり、管理された再現可能な方法で適用すべきだと説明しています。
この分離により、アプリプロセスが再起動または重複した場合でも、誤ってマイグレーションが実行される可能性を下げられます。権限の高い認証情報は、通常の長時間稼働サービスの環境変数ではなく、デプロイ用シークレットの経路に保存してください。
ロールアウトでバッチが2回適用されないことを確認する
使い捨てのデータベースまたは復元したスナップショットを使ってデプロイをテストします。複数のアプリレプリカを起動し、レプリカを再起動してからデプロイコマンドを再実行してください。マイグレーションステージは既存のスキーマ状態を報告し、2回目に変更を加えないようにします。
JetBrainsは、通常のアプリケーション起動前に、デプロイ手順としてマイグレーションを実行するという運用ルールをまとめています。
アプリの再起動でスキーマが変更されず、1回のマイグレーション失敗でリリースがブロックされ、ロールアウトを繰り返してもデータベースが変更されない状態になれば、予防策は完成です。すでに重複実行が発生している場合は、関連するZimaSpaceの記事重複マイグレーションの診断を復旧手順として参照してください。
サポートとヒント
もっと読む

Plexは別のDockerコンテナとGPUを共有できますか?
Plexと別のコンテナは同じGPUにアクセスできることが多いですが、ドライバーのサポート、デバイスマッピング、ビデオエンジンの負荷、メモリ、復旧動作をテストする必要があります。

Plexのエラーがクライアント側とサーバー側のどちらに起因するかを見分ける方法
別のクライアントで同じ項目を再現し、セッションパスを比較してから、スコープによって障害の実際の所在が特定された後にのみサーバーの証拠を収集してください。

Plexのキャッシュとトランスコード用一時ストレージを設定する方法
永続的な Plex の状態を保護しつつ、トランスコードの一時ファイルを適切なローカルストレージに配置し、クリーンアップ、空き容量、再起動時の動作を確認します。

