OpenShip公式は、旧バージョンへ「1クリック」で戻せる機能と、各デプロイを不変のスナップショットとして扱う仕組みを説明しています。(openship.io)
症状:管理画面ではロールバック成功なのに、旧コードが新しいデータベースを読み込めない。
最短解:OpenShipのロールバックを、旧版の起動、設定復元、データベース移行、通信切り替え、バックグラウンド処理の5指標で受け入れ判定してください。
対象となるチーム
OpenShipでAI SaaS、管理画面、Agent APIを本番運用し、リリース承認にロールバック証拠を組み込みたいチーム向けです。
データベース、Worker、ストリーミング応答、WebSocketを使うサービスでは、単純なコンテナ入れ替えだけでは復旧判定を出せません。運用担当者、リリース担当者、データ復旧責任者が同じ記録を確認できる状態を作ります。
ロールバック成功の定義
まず、成功を3段階に分けます。OpenShipの画面表示は「制御操作が完了した」ことを示すだけで、ユーザーのリクエストが戻ったことまでは証明しません。
| 判定層 | 確認対象 | 合格条件 | 不合格時の処置 |
|---|---|---|---|
| 制御層 | ロールバック操作、対象デプロイ | 対象バージョンと操作ログが一致する | 操作ログと対象IDを再確認する |
| 実行層 | 旧コンテナ、起動コマンド、依存関係 | 新しいインスタンスとして起動し、ログに致命的エラーがない | 旧イメージ、依存関係、起動設定を再取得する |
| 業務層 | 主要API、認証、ストリーミング、管理画面 | 重要なユーザー操作が完了し、許容範囲内のエラーに収まる | 新旧版を隔離し、手動復旧へ切り替える |
OpenShipの公式説明には、イミュータブルなデプロイ、旧版保持、ヘルスチェック、ゼロダウンタイム切り替えが記載されています。ただし、これはプラットフォームの機能説明であり、あなたのアプリケーション、データベース、外部APIまで自動的に整合するという意味ではありません。(openship.io)
合格基準には、復旧目標、主要エンドポイント、データ欠損の許容範囲、降格運転の範囲を明記してください。復旧時間や停止時間を記事や社内資料に固定値で書く場合は、プロジェクト要件または自社の実測記録を根拠にします。
旧版アーティファクトと起動条件
OpenShipのロールバックで最初に確認するのは、戻す先のバージョンが本当に再利用できるかです。Gitのブランチ名や可変タグだけを証拠にせず、デプロイID、コミット識別子、イメージ識別子、ビルドログを保存します。
コンテナイメージはタグが変更される可能性があるため、重要な本番版ではダイジェストで固定する方が再現性を確保しやすくなります。ダイジェストが同じなら、同じ内容のイメージを取得できるという考え方は、公式のコンテナ資料でも説明されています。詳しくはイメージのダイジェストに関する公式説明を確認してください。(docs.docker.com)
旧コンテナを再起動するだけで十分ですか。
十分ではありません。残留コンテナが持つ一時ファイルや手動変更に依存していないかを調べるため、旧版の停止後に新しいインスタンスとして起動します。依存パッケージの取得、起動コマンド、ポート待受、ログ出力が同じ結果になるかを確認してください。
受入時には、次の4点を記録します。
- 対象デプロイのIDとコミット識別子
- 実際に起動したイメージの識別子
- 起動コマンドと依存関係の取得結果
- ロールバック前後のデプロイログ
旧版の取得に失敗した場合、ロールバック操作を何度も繰り返さず、まずアーティファクト保管先と保持ポリシーを確認します。対象版を再構築して代用する場合は、「同じソースから作った別ビルド」として扱い、元のアーティファクト復元とは分けて承認してください。
設定、秘密情報、外部サービス
コードだけ戻っても、環境変数が新しいサービスを指したままなら、旧版と新設定の組み合わせになります。特にAI SaaSでは、モデルAPIの接続先、認証キー、Webhook先、キュー名、機能フラグの不一致が復旧直後の障害を起こします。
OpenShipの公式資料では、環境変数や秘密情報をプロジェクト単位で管理する構成が説明されています。ロールバックの受入では、保存値そのものを貼り付けず、設定のバージョン、更新時刻、ハッシュ、権限状態だけを記録します。(openship.io)
OpenShipのロールバックで古い環境変数まで戻りますか。
自動的に戻ると決めつけないでください。旧デプロイに紐づく設定が復元されるのか、現在のプロジェクト設定を再利用するのか、秘密情報だけ別管理なのかを、実際の環境で確認します。
| 設定項目 | テスト方法 | 証拠の場所 | 合格基準 | 失敗時の処置 |
|---|---|---|---|---|
| API接続先 | 旧版から疎通確認 | アプリログ、監査ログ | 旧版が想定する接続先へ到達する | 接続先を旧版用に戻す |
| 秘密情報 | 値を表示せず権限と版を確認 | 秘密情報の履歴 | 必要な権限だけが有効 | 権限を修正し再起動する |
| 機能フラグ | 主要機能をON・OFFで確認 | 設定履歴、テスト結果 | 旧版が想定する分岐になる | フラグを明示的に固定する |
| 外部Webhook | 疑似イベントを送信 | 送受信ログ | 重複送信や誤配送がない | 送信を停止し手動確認する |
データベース移行と永続データ
データベース移行後でもOpenShipのアプリは戻せますか。
アプリケーションだけなら戻せる場合がありますが、データベースまで自動的に過去の状態へ戻るとは考えないでください。新しいカラムを追加しただけの後方互換移行、旧版でも読める状態を保つ可逆的な移行、既存カラム削除や型変更を含む破壊的な移行を分けます。
典型的には、次の順番で進めます。
- 新しいカラムやテーブルを追加する。
- 旧版と新版の双方が読める状態を維持する。
- データを段階的に書き込む。
- 旧版を停止できることを確認する。
- 最後に不要な構造を削除する。
破壊的な移行を実施した後に旧版へ戻す場合、アプリケーションのロールバックだけでは不十分です。バックアップの復元、復元後の整合性確認、復元前後の差分確認を独立した手順として扱います。OpenShipが提供するバックアップや復元機能を使う場合でも、実際の復元結果が残っていなければ、データ復旧の証拠にはなりません。公式のインストール資料でも、データベースや永続サービスが別の運用対象になることが確認できます。(openship.io)
注意:ロールバック対象にデータベースを含めると、ロールバック後に発生した注文、会話、ジョブ状態などを失う可能性があります。データ復元の承認者をアプリ担当者と別に置き、復元範囲を先に決めてください。
ヘルスチェックと通信切り替え
OpenShipの公式ページは、ヘルスチェック後に新しいコンテナへトラフィックを切り替える構成を説明しています。(openship.io) ただし、単純なHTTPステータスだけでは、データベース接続、認証、外部API、ストリーミング処理まで確認できません。
テスト対象を分けて記録します。
- 一般的なHTTPリクエスト:ログイン、主要画面、代表的なAPI
- ストリーミング応答:途中で切断されず、完了イベントを受け取れるか
- WebSocket:接続、再接続、切断時の状態保存
- エラーログ:切り替え前後の5xx、タイムアウト、認証失敗
- 流量経路:ドメイン、リバースプロキシ、内部サービスの接続先
OpenShipのロールバック中にリクエスト中断を避けるにはどうしますか。
ヘルスチェックを「プロセスが生きているか」だけにせず、読み取り専用の業務確認まで含めます。新しい旧版インスタンスが準備できる前に流量を移さないこと、長時間接続を新旧どちらで処理するかを決めること、切り替え後に新規接続と既存接続を別々に確認することが重要です。
長時間のストリームやWebSocketを使うAgent APIでは、完全な無中断を宣伝文句から判断しません。実際の接続ログ、切断数、再接続後のタスク状態を根拠に、許容できる降格範囲を決めてください。
Worker、キュー、二重実行
新旧バージョンが短時間同時に存在すると、定期処理やキューの消費が二重になることがあります。AI Agentのツール呼び出し、メール送信、課金処理、外部APIへの更新処理は、二重実行による副作用が大きいため、アプリの起動確認だけで合格にしません。
受入テストでは、次の証拠を残します。
- タスクIDとキューのメッセージID
- 取得、処理中、完了、失敗の状態履歴
- 外部サービスへ送ったリクエストの識別子
- 同じ副作用が複数回発生していないこと
- 重複を検知した場合の停止、再試行、補償処理
バックグラウンドタスクがロールバック後に重複実行される理由は何ですか。
新旧Workerが同じキューを読み、片方が処理済み状態を書き込む前にもう片方が同じメッセージを取得するためです。ロールバック時はWorkerを先に停止する、リースやロックを確認する、処理を冪等にする、外部副作用に一意なリクエストIDを付ける、といった制御が必要です。
重複を見つけたら、再実行を続ける前にキュー消費を止めます。その後、処理済み状態と外部副作用を照合し、再実行、取り消し、手動補償のどれを選ぶかを責任者が決めます。
本番受入の可否判定
次のチェックリストを、リリース承認記録にそのまま添付してください。チェックが付かない項目がある場合は、全面的な本番投入ではなく、制限付き公開または禁止にします。
- [ ] 対象バージョンのデプロイID、コミット識別子、アーティファクト識別子を保存した
- [ ] 残留コンテナではなく、新しいインスタンスとして旧版を起動した
- [ ] 起動コマンド、依存関係、ポート待受、ログ出力を確認した
- [ ] ロールバック後に実際に適用された環境変数の版と更新時刻を記録した
- [ ] 秘密情報の値を露出させず、権限と接続先を確認した
- [ ] データベース移行を後方互換、可逆、破壊的のいずれかに分類した
- [ ] 破壊的な移行について、アプリ復旧とは別のデータ復元手順を確認した
- [ ] HTTP、ストリーミング、WebSocketの実リクエストを実行した
- [ ] 切り替え前後のエラー、切断、タイムアウトを保存した
- [ ] Worker、定期処理、キューの重複実行がないことを確認した
- [ ] 重複発生時の停止と補償処理の担当者を決めた
- [ ] 実施者、承認者、復旧責任者、発動条件を記録した
判定は「承認」「制限付き承認」「禁止」の3種類にします。例えば、旧版の起動とHTTP確認は通ったが、破壊的なデータベース移行の復元証拠がない場合は、ロールバック可能とは書かず、制限付き承認または禁止にします。
現行構成との比較と判断
OpenShipを使わず、手作業のコンテナ操作や個別のスクリプトだけで戻す構成は、初期費用を抑えられる一方で、対象版、設定、通信経路、Workerの状態が別々に管理されがちです。担当者の記憶に依存し、承認ログが分散し、データベース復元とアプリ復旧の境界も曖昧になります。
OpenShipは不変デプロイ、旧版保持、ログ、ヘルスチェック、CLIやダッシュボードからの操作を一つの運用経路にまとめやすい点が利点です。(openship.io) ただし、データベースの破壊的変更、外部サービスの状態、長時間接続、Workerの冪等性までは自動で保証しません。
本番前に一度だけボタンを押すのではなく、隔離した検証環境で「新版を出す → 実データに近い処理を行う → 旧版へ戻す → 主要業務を再確認する」流れを記録してください。ローカルのビルド端末を常時稼働させにくい場合や、チームで分離された検証環境が必要な場合は、クラウドMacの一時利用環境や米国向けMacレンタル環境を比較すると、再現用の端末を固定費なしで用意しやすくなります。
KvmzenのMac環境は、長期の高負荷運用や物理インターフェースが必要な本番基盤の代替ではありません。一方で、OpenShipの本番受入、CI/CDの再現、Agentサービスの一時的な復旧検証を行う用途なら、自社端末だけに依存するより、担当者ごとの環境差を減らしやすい選択肢です。
