ホームページの公開作業を自動にすると、手で作業していたころの「うっかり」は減ります。その代わりに、自動の仕組みそのものが壊れたとき、同じ間違いを毎回、確実に繰り返すようになります。送り元のフォルダが空のまま転送すれば、本番のファイルが消えます。ビルドが失敗したのに処理が止まらなければ、壊れたページが公開されます。
この記事では、サイトの公開(デプロイ)を自動化するときに仕組みのほうが壊れる型を9つに分け、それぞれの防ぎ方を整理します。記事の中身の確認は「記事更新の自動化は品質ゲートで決まる」、更新・バックアップ・死活監視は「ホームページ保守の自動化」、自動化の全体像は「サイト運用のAI・自動化は棚卸しから」で扱いました。今回は、ファイルを本番に届けて切り替える工程に絞ります。
この記事が主に根拠にした情報:rsync の公式マニュアル(--delete・--dry-run・--max-delete と終了コード)、GNU Bash のマニュアル、GitHub Docs(Actions の同時実行の制御・環境の保護・料金)、web.dev の HTTP キャッシュの解説、Google 検索セントラルの一時停止とインデックス制御、DORA のソフトウェアデリバリーの指標、Google の SRE ワークブック、米国証券取引委員会(SEC)の命令書と GitLab の事故報告。いずれも2026年10月31日に確認しました。
| この記事で分かること | 答えの要点 |
|---|---|
| どこが壊れやすいのか | ビルド・転送・切替・公開後の4段階に9つの型(第2〜3章) |
| ファイルを消さないには | dry-run・除外・削除の上限・送り元の確認(第4章) |
| 失敗を止めるには | 終了コードで止め、途中の状態を公開しない(第5章) |
| 戻せる形にするには | リリースごとのディレクトリとリンクの切替(第10章) |
| 費用は | 3段階で初期6〜80時間、月額0〜80ユーロ(第12章) |
| 何から始めるか | 4週間の導入手順とチェックリスト(第16・18章) |
1. いま何が起きているか:自動化で「壊れる場所」が変わった
サイトの公開を自動にする事業者は増えています。GitHub に変更を送ると、ビルド・テスト・転送までが自動で走る形は、もう大きな会社だけのものではありません。GitHub の料金表では、無料プランにも毎月12ドル分の実行枠が含まれ、標準の Linux 実行環境なら1分0.006ドル、おおよそ2,000分ぶんに当たります。公開リポジトリでは標準の実行環境が無料です。
失敗の場所が「人の手元」から「仕組みの中」へ移った
手作業の公開では、失敗はたいてい1回きりです。ファイルを1つ上げ忘れても、次に気づいて直せば終わります。自動化すると、同じ設定の誤りが毎回の公開で繰り返されます。しかも誰も画面を見ていないので、気づくのが遅れます。
DORA は「壊れた割合」と「戻るまでの時間」を測る
Google Cloud の DORA(DevOps Research and Assessment)は、ソフトウェアの届け方を5つの指標で測ることを勧めています。変更が本番に届くまでの時間、公開の頻度、失敗した公開からの回復時間、公開後にすぐ手当てが要った割合(変更失敗率)、予定外の手直しの公開の割合です。DORA は、これらを一律の目標にすると数字合わせが起きると注意しています。小規模なサイトでは、頻度を上げる前に、壊れたときにすぐ戻れる状態を作るほうが先です。
PHP 8.2 のセキュリティ修正が2026年12月31日で終わることも重なります。版を上げる時期は、デプロイの仕組みが壊れやすい時期でもあります。
図のとおり、型の多くは転送と切替の前後に集まります。ここに確認と停止の仕組みを置けば、9つのうち6つは手前で止められます。
2. デプロイとは何か:記事のチェック・保守との境界
ここでいうデプロイは、手元やリポジトリにある変更を、本番のサーバーに届けて切り替える工程です。ビルド(CSS や JavaScript の生成、依存パッケージの取得)、転送、切替、公開後の確認までを含みます。
ほかの工程とどう分けるか
公開前のチェックには、記事の中身を見るものと、届け方を見るものがあります。この記事は後者だけを扱います。
| 工程 | 何を確かめるか | 扱う記事 |
|---|---|---|
| 記事の品質ゲート | 字数・出典・表記・画像 | 記事更新の品質ゲート |
| デプロイの安全 | 削除・上書き・失敗の停止・切替・戻し | この記事 |
| 保守 | 更新・バックアップ・死活監視・証明書 | 保守の自動化 |
| 表示速度の監視 | Core Web Vitals の推移 | Core Web Vitals の監視 |
境界をはっきりさせるのは、同じ確認を2か所でして、どちらも中途半端になることを避けるためです。
手作業でも自動でも、壊れる型は同じ
手順書を見ながら打つ段階でも、GitHub などに変更を送ると自動で走る段階でも、壊れる型は同じです。違うのは、誰がいつ気づけるかです。自動に進むほど、止める条件と知らせる先を、人が先に決めておく必要があります。
3. 壊れる9つの型の全体地図
ここからは、9つの型を一覧にして、どこで起き、いつ気づき、何で防ぐかを並べます。
| 型 | 何が起きるか | 気づく時点 | 主な防ぎ方 |
|---|---|---|---|
| 1. 想定外の削除 | 本番だけのファイルが消える | 利用者の指摘 | dry-run・除外・上限 |
| 2. 設定・秘密の上書き | 本番の設定が手元の値になる | 公開直後のエラー | 設定を転送対象から外す |
| 3. ビルド失敗のまま公開 | 古いCSSや欠けたファイル | 表示崩れの報告 | 終了コードで止める |
| 4. 途中で止まった転送 | 新旧のファイルが混在 | 一部ページのエラー | 別ディレクトリで切替 |
| 5. キャッシュ | 古い表示が残る、新旧が混ざる | 利用者ごとに違う | ファイル名の指紋・HTMLは再検証 |
| 6. DB マイグレーション | 古いコードが動かない | 戻そうとしたとき | 先にバックアップ・段階的な変更 |
| 7. 版の不一致 | 手元で動き本番で落ちる | 公開直後の500 | lockfile・本番の版で解決 |
| 8. 自動処理の競合 | 2本の公開が同時に走る | 不定期の不具合 | 同時実行の制御・ロック |
| 9. 戻せない・確認抜け | 戻し方がない、壊れに気づかない | 数時間〜数日後 | リリースの保存・スモークテスト |
型1〜4は失敗に気づかず先へ進むこと、型5〜7は手元と本番の前提のずれ、型8〜9は運用の約束がないことが原因です。
4. 型1・2:想定外の削除と、設定・秘密情報の上書き
いちばん被害が大きく、いちばん防ぎやすいのがこの2つです。どちらも、転送の対象と除外の境界があいまいなときに起きます。
rsync の --delete は何を消すのか
rsync はサーバーへの転送でよく使われる道具で、--delete を付けると送り元にないファイルを送り先から消します。公式マニュアルは「使い方を誤ると危険になり得る」と明記し、先に --dry-run(-n)で削除されるファイルを確かめるよう勧めています。本番にしかないファイルは思ったより多く、除外に入れ忘れたものは次の公開で消えます。
| 本番にしかないもの | 例 | 守り方 |
|---|---|---|
| 設定・秘密情報 | .env、wp-config.php |
除外に入れ、転送対象にしない |
| 利用者のアップロード | uploads/、storage/app/public |
公開ディレクトリの外に置き、リンクで参照 |
| サーバーで作るデータ | 取得した為替・天気、生成画像 | 除外に入れ、作る処理と置き場を分ける |
| ログ・一時ファイル | storage/logs/ |
除外に入れる |
| 退避したバックアップ | .env.bak-日付 |
除外に入れ、公開領域の外に置く |
マニュアルによれば、除外したファイルは削除の対象からも外れます(--delete-excluded を付けない限り)。除外の一覧が「消さないものの一覧」を兼ねます。
送り元が空のとき、何が起きるか
いちばん怖いのは、送り元のフォルダが空、または別の場所を指しているときです。--delete 付きで空のフォルダを送ると、送り先は空に揃えられます。
2015年1月には、ゲーム配信サービス Steam の Linux 版で、rm -rf "$STEAMROOT/"* という1行が、変数が空のときにルート直下のすべてを消す命令になり、利用者のファイルが消えたと GitHub の課題に報告されました。
防ぎ方は単純です。転送の前に、送り元に必ずあるはずのファイル(index.php など)があるかを確かめ、なければ止めます。パスに使う変数は ${DIR:?} と書くと、空のときに止まります。
削除の件数に上限を置く
rsync には --max-delete=NUM という指定があります。マニュアルによれば、削除が指定の件数を超えると、それ以降の削除をすべて飛ばし、終了コード25で終わります。--max-delete=0 にすると、何も消さずに「余分なファイルがある」という警告だけを出せます。
ふだんの公開で消えるのは数件から数十件です。上限をふだんより少し多い値に置くと、大量削除を手前で止められます。
秘密情報を上書きしない、漏らさない
設定ファイルを転送すると、手元の開発用の値で本番を上書きします。デバッグ表示がオンになり、エラー画面に設定値が出ることもあります。Laravel の公式ドキュメントは、本番では APP_DEBUG を必ず false にするよう注意し、index.php をプロジェクトの直下に移すと設定ファイルが公開されると警告しています。本体を公開ディレクトリの外に置き、public/ だけを見せる構成にします。
GitHub には、秘密情報を含む push を止める機能(push protection)があります。CI で使う本番の鍵は「環境(environment)」の秘密情報に置くと、承認などの保護ルールを通ったジョブだけが読めます。OWASP のチートシートも、秘密情報をコードと分け、使える範囲を最小にすることを基本にしています。
DevNJ の運用で実際に起きたこと
DevNJ のサイトでも、未コミットの変更が本番に出かけた場面、手元で作ったキャッシュに開発用の依存が載って本番でエラーになった場面、サーバーで毎時作るデータが --delete で消えかけた場面がありました。いまは公開するコミットを git archive で書き出して送り、キャッシュとサーバーで作るデータを除外しています。多くは、dry-run の削除予定の一覧を見て気づいたものです。
5. 型3・4:ビルド失敗のまま公開と、途中で止まった転送
次に多いのが、途中で失敗したのに処理が最後まで進む型です。シェルスクリプトは、何も指定しないと失敗しても次の行に進みます。
終了コードで止める
コマンドは終了コードを返し、0が成功、それ以外が失敗です。GNU Bash のマニュアルによれば、set -e は0以外で終わった時点でスクリプトを止め、set -u は未定義の変数をエラーにし、set -o pipefail はパイプの途中の失敗も全体の失敗として扱います。
| 指定 | 何を止めるか | 指定しないと起きること |
|---|---|---|
set -e |
0以外で終わったコマンドの後 | ビルド失敗の後も転送が走る |
set -u |
未定義の変数の使用 | 打ち間違えた変数が空になる |
set -o pipefail |
パイプの途中の失敗 | build | tee log が成功扱い |
| 送り元の確認 | 必須ファイルがない状態 | 空のフォルダで本番を揃える |
set -e には例外があります。if の条件の中や、&& と || でつないだ列の途中で失敗したコマンドでは止まりません。大事な工程は、失敗したら明示的に exit 1 する書き方にしておくと確実です。
rsync の終了コードを読み分ける
rsync は、失敗の種類ごとに違う終了コードを返します。公式マニュアルの一覧から、デプロイでよく出るものを抜き出しました。
| 終了コード | 意味 | デプロイでの扱い |
|---|---|---|
| 0 | 成功 | 次の工程へ |
| 23 | エラーによる一部の転送 | 止めて、どのファイルかを確認 |
| 24 | 送り元のファイルが途中で消えた | ビルド中の転送を疑い、止める |
| 25 | 削除の上限で削除を止めた | 削除予定の一覧を人が確認 |
| 30・35 | 通信のタイムアウト | 再実行の前に、途中の状態を確認 |
「一部だけ転送された」状態を成功として扱わないことが要点です。23と24は、本番に新旧のファイルが混ざっている可能性を示します。
図の上の段は、dry-run の結果から削除予定の件数を数えて判断する基準です。下の段は、各工程の終了コードで判断する基準です。どちらも「止める」側に倒すと、誤報はあっても事故にはなりません。
途中で止まると新旧が混ざる
本番のディレクトリへ直接転送すると、途中で止まったときに新旧のファイルが混ざった状態が残ります。rsync の --delay-updates は更新を最後にまとめて置き換え、マニュアルの言葉では「少し原子的に近づく」程度です。確実なのは、第10章の別ディレクトリに置いてから一度に切り替える方式です。
6. 型5:キャッシュが古い表示を残す
公開が成功しても、利用者の画面が変わらないことがあります。原因の多くはキャッシュです。キャッシュはブラウザ、CDN、アプリケーションの3か所にあり、それぞれ消し方と効き方が違います。
ブラウザと CDN のキャッシュ
web.dev の HTTP キャッシュの解説は、中身が変わらない URL には Cache-Control: max-age=31536000(1年)を付け、中身が変わったらURL のほうを変えることを勧めています。app.3f9a1c.css のように、ファイルの中身から作った文字列(指紋)を名前に含めれば、新しい版は新しい URL になるので、古いキャッシュとぶつかりません。
HTML のように URL を変えられないものは、no-cache を付けて、使う前に毎回サーバーへ確認させます。ETag などと組み合わせれば、変わっていないときは小さな 304 の応答で済みます。
| 対象 | 推奨の指定 | 理由 |
|---|---|---|
| 指紋つきの CSS・JS・画像 | max-age=31536000 |
中身が変われば URL が変わる |
| HTML | no-cache + ETag |
毎回確認し、変わっていなければ304 |
| 指紋のない画像・PDF | 短めの max-age | 差し替えても名前が同じ |
| CDN の上の HTML | 公開時に削除(パージ) | CDN が古い版を配り続ける |
キャッシュされた古い HTML が、ビルドで消した古い名前のCSSを読みにくると表示が崩れます。直前の版のアセットを数日残すと避けられます。
アプリケーションのキャッシュ
Laravel の公式ドキュメントは、本番の公開で php artisan optimize を実行し、設定・ルート・ビューなどをキャッシュするよう勧めています。ただし、設定をキャッシュすると .env は読まれなくなり、設定ファイルの外で呼んだ env() は null を返します。手元で動いていたコードが、本番でだけ値を取れなくなる典型です。
キュー(裏で動く処理)のワーカーも古いコードのまま動き続けるため、Laravel は公開後に php artisan reload で再起動するよう案内しています。
7. 型6:データベースのマイグレーション
データベースの構造を変える処理を、マイグレーションと呼びます。列を足す、名前を変える、型を変える、といった変更です。ファイルは前の版に戻せても、データベースの構造は自動では戻りません。
戻せない変更を見分ける
列や表の削除、名前の変更、型の変更は、古いコードから見ると「あるはずの列がない」状態を作ります。ファイルだけ前の版に戻すと、今度は古いコードが新しい構造の上で動いて落ちることになります。
| 変更 | 古いコードは動くか | 安全な進め方 |
|---|---|---|
| 列を足す(空を許す) | 動く | そのまま公開してよい |
| 表を足す | 動く | そのまま公開してよい |
| 列の名前を変える | 動かない | 足す→両方に書く→移す→消すの4段階 |
| 列を消す | 動かない | 参照をなくした版の公開後に消す |
| 型を変える | 場合による | 新しい列を足して移す |
この「足してから、移して、最後に消す」進め方は、Martin Fowler が「並行変更(Parallel Change)」として整理した手法です。1回の公開で構造とコードを同時に変えないことで、どの時点でも1つ前の版に戻せます。
本番での実行を止める仕組みを使う
Laravel のマイグレーションは、本番では実行前に確認を求めます。自動の公開では --force を付けて確認を飛ばすので、その前にバックアップを取る工程を必ず置きます。複数のサーバーで同時に公開するときは、--isolated を付けると、ロックを取って1台だけで実行されます。
GitLab.com は2017年1月31日、作業者が本番のデータベースのデータ約300GBを誤って消し、事故報告によれば6時間ほどのデータ(プロジェクト約5,000件、コメント約5,000件、利用者約700人)を失いました。定期バックアップは道具の版が合わずに失敗し、その通知メールも受信側に拒否されていました。バックアップは、取得と失敗の通知の両方を確かめて初めて役に立ちます。
8. 型7:依存関係と PHP などの版の不一致
手元では動くのに、本番では動かない。この型の原因の多くは、手元と本番で、PHP や依存パッケージの版が違うことです。
lockfile で版を固定する
npm の npm ci は、lockfile(package-lock.json)がなければ動かず、package.json と食い違えばエラーで止まり、lockfile を書き換えません。既存の node_modules も先に消してから入れ直します。公開用のビルドでは npm install ではなく npm ci を使うと、手元と同じ版が入ります。
PHP の Composer も、composer.lock に版を固定します。Composer の platform 設定を使うと、手元の PHP が新しくても、本番の PHP の版を前提に依存を解決できます。公式ドキュメントは、この設定は本当の非互換を隠すことがあるため、公開時に check-platform-reqs も実行するよう勧めています。
PHP のサポート期間
PHP の公式サイトによれば、各系列のセキュリティ修正の期限は次のとおりです。
| 系列 | 公開 | 通常のサポート | セキュリティ修正の期限 |
|---|---|---|---|
| 8.2 | 2022年12月 | 2024年12月31日まで | 2026年12月31日 |
| 8.3 | 2023年11月 | 2025年12月31日まで | 2027年12月31日 |
| 8.4 | 2024年11月 | 2026年12月31日まで | 2028年12月31日 |
| 8.5 | 2025年11月 | 2027年12月31日まで | 2029年12月31日 |
PHP 8.2 を使っているサイトは、2か月以内に上げる計画が要ります。上げるときは、手元・CI・ステージング・本番の4か所の版を揃えてから進めます。1か所だけ先に上げると、この型の不具合が出ます。
レンタルサーバーでは、コマンドラインの PHP と Web の PHP の版が違うことがよくあります。cron の処理だけが落ちるときは、まずここを疑います。
9. 型8:同時に走る自動処理の競合
自動化が進むと、公開の処理が1本ではなくなります。記事の自動生成、定期的なデータの取得、手作業の修正が、同じリポジトリや同じサーバーに同時に書き込もうとします。
CI での同時実行を制御する
GitHub Actions には、同時実行(concurrency)の制御があります。GitHub Docs によれば、同じグループ名の実行は同時に1つだけ動き、待ちは1つだけ残ります。新しい実行が来ると、待っていた実行は取り消されます。cancel-in-progress: true にすると、動いている実行も取り消します。
本番への公開では、動いている公開を途中で取り消さないほうが安全です。途中で止めると、型4の「新旧の混在」が起きるからです。待ちを残したいときは queue: max で最大100件まで並べられますが、cancel-in-progress とは組み合わせられません。
| 設定 | 動き | 向いている場面 |
|---|---|---|
| 指定なし | 何本でも同時に走る | 本番の公開には向かない |
concurrency のみ |
1本実行、1本待ち | 最新の版だけ出せばよい公開 |
cancel-in-progress: true |
実行中も取り消す | プレビューの表示、テスト |
queue: max |
最大100件を順に処理 | すべての公開を順番に出す |
リポジトリへの書き込みの競合
自動で記事を作る処理と、人の修正が同じブランチに push すると、後から送った側は拒否されます。Git の公式ドキュメントにあるとおり、履歴が先に進んだブランチへの push は、そのままでは受け付けられません。ここで強制的に上書きすると、相手の変更が消えます。
push の前に最新を取り込み(rebase)、その上で公開する手順にすると、この事故は防げます。DevNJ のサイトでも、コラムの自動生成と手作業の修正がぶつからないよう、push の前に rebase する手順を決めています。
サーバーの cron が公開の途中でファイルを書き換えることもあります。定期処理が書く場所は、公開で置き換える場所の外に置きます。
10. 型9:戻せない構成と、公開後の確認抜け
最後の型は、壊れた後に効いてきます。戻し方がない、または壊れたことに気づかない状態です。
リリースごとのディレクトリとリンクの切替
戻しやすい構成の基本は、版ごとに別のディレクトリへ置き、公開に使うリンクだけを切り替える形です。releases/20261031-1015/ に新しい版を置き、確認が済んだら current というリンクをそちらへ向けます。戻すときは、リンクを前の版へ向け直すだけです。
Linux の rename は、置き換え先がすでにあっても原子的に置き換えると公式マニュアルに書かれています。新しいリンクを別名で作ってから rename で入れ替えると、途中の状態が生まれません。PHP の配備ツール Deployer は、この方式を使い、既定で直近10版を残します。
| 切替の方式 | 混在の時間 | 戻す方法 | 向いているサイト |
|---|---|---|---|
| 本番へ直接上書き | 転送の間ずっと | 前の版を再転送 | 静的で小さいサイト |
| 一時置き場から一括置換 | 短い | 前の版を再転送 | 共有サーバーの小規模サイト |
| リリース+リンク切替 | ほぼなし | リンクを戻す | PHP・CMS のサイト |
| 2系統の入れ替え | なし | 振り分けを戻す | 止められないサイト |
最後の方式はブルーグリーン・デプロイと呼ばれます。どの方式でも、データベースの構造の変更はリンクを戻しても戻りません。第7章の進め方と組み合わせます。
戻すまでの時間は、そのまま利用者がエラーを見ている時間です。リンクの切替で戻せる構成にしておくと、判断に迷う時間も短くなります。「戻してから原因を調べる」が選べるからです。
戻すことが事故を広げた例
米国証券取引委員会(SEC)の2013年の命令書によれば、米 Knight Capital は2012年7月、新しいコードを8台のサーバーへ配る際に1台への配布を漏らし、2人目の確認もありませんでした。8月1日、その1台の古い機能が45分で400万件を超える注文を出し、対応の途中で正しい7台からも新しいコードを外したため、被害が広がりました。損失は4億6,000万ドルを超えました。配布の照合と戻し方の取り決めがない危うさは、サイトの公開でも同じです。
公開直後のスモークテスト
公開の直後に、主要なページが返す応答コードと、ページ内の決まった文字列を自動で確かめます。これをスモークテストと呼びます。Laravel には /up という確認用のルートが標準であり、アプリケーションが起動できれば200、例外が出れば500を返します。
| 確認する項目 | 方法 | 失敗したとき |
|---|---|---|
| 主要5〜10ページの応答 | 200 が返るか | リンクを前の版へ戻す |
| ページ内の文字列 | 会社名や見出しがあるか | 表示崩れを疑う |
| 確認用のルート | /up が200か |
設定とキャッシュを確認 |
| フォームのテスト送信 | メールが届くか | 送信設定を確認 |
| noindex の有無 | 本番に noindex がないか | すぐに外して再公開 |
| robots.txt | 200 で中身が正しいか | 検索の巡回が止まる前に直す |
最後の2行は、検索に直接響きます。Google の一時停止の案内は、robots.txt を 503 で返すとすべての巡回が止まると注意しています。ステージングで付けていた noindex が本番に持ち込まれると、ページは検索結果から外れていきます。
直後の確認は自動にし、失敗したら人を待たずに前の版へ戻すところまで仕組みにしてかまいません。戻すのはファイルとリンクだけで、データベースには触れないからです。
公開の作業でサイトを止める場合も、Google の案内は 503 を返すのを1〜2日程度にとどめるよう書いています。メンテナンス画面のまま週末をまたがないことが大切です。
11. ステージングとカナリア:小さなサイトでどこまで要るか
本番と同じ構成の確認用の環境をステージング、新しい版を一部にだけ出して様子を見る方法をカナリアと呼びます。小さなサイトでも、要る場面と要らない場面があります。
ステージングの守り方
ステージングが検索結果に出ないよう、noindex よりパスワードでの保護を使います。noindex で隠した場合は、それが本番に持ち込まれていないかを第10章のスモークテストで毎回確かめます。
カナリアは「一部から出す」考え方
Google の SRE ワークブックは、カナリアを「変更を、一部に・期限つきで出して評価すること」と定義し、例として5%の利用者に出す形を示しています。同時に走らせるカナリアは1つだけにするよう勧めています。
2024年7月19日には、セキュリティ製品の更新が一斉に配られ、Microsoft の推計で約850万台の Windows 端末が起動できなくなりました。複数のサイトを同じ仕組みで更新するなら、まず1サイトに出して確かめてから残りに広げます。
| サイトの種類 | ステージング | 一部からの公開 | 理由 |
|---|---|---|---|
| 静的な会社案内 | プレビューで代用 | 不要 | 戻すのが簡単 |
| CMS のサイト | 推奨 | 不要 | プラグインと PHP の確認 |
| 問い合わせ・予約 | 必須 | 不要 | フォームが止まると機会を失う |
| ネットショップ | 必須 | 推奨 | 決済と在庫の確認 |
| 複数サイトの一括更新 | 必須 | 必須 | 1つ目で止められる |
ステージングは本番と同じ版の PHP・同じ設定の種類で作ることが前提です。版が違うステージングは、第8章の不一致を見逃します。
12. 費用と工数の幅
デプロイの安全対策は、どこまで進めるかで費用の幅が大きく変わります。次の表は DevNJ の目安で、PHP か CMS を使うサイト1つを想定しています。
| 段階 | 中身 | 初期の工数 | 月額(€) |
|---|---|---|---|
| 1. スクリプトの安全化 | set -euo pipefail、送り元の確認、dry-run、除外、削除の上限、スモークテスト |
6〜12時間 | 0 |
| 2. CI とリリースの切替 | 自動ビルド、lockfile、同時実行の制御、リリースごとのディレクトリ、通知 | 16〜32時間 | 0〜20 |
| 3. ステージングと DB | ステージング、マイグレーションの手順、公開前のバックアップ、自動の戻し | 40〜80時間 | 20〜80 |
GitHub Actions の実行枠は、小さなサイトの公開なら無料の範囲に収まることが多く、月額の多くはステージング用のサーバーや監視の費用です。
時間単価80ユーロで外注した場合の初期費用は、次のようになります。円は1ユーロ175円で換算した概算です。
| 段階 | 初期費用(€) | 初期費用(円の概算) | 1年目の合計(€) |
|---|---|---|---|
| 1 | 480〜960 | 約8.4万〜16.8万円 | 480〜960 |
| 2 | 1,280〜2,560 | 約22.4万〜44.8万円 | 1,280〜2,800 |
| 3 | 3,200〜6,400 | 約56万〜112万円 | 3,440〜7,360 |
1年目の合計は、初期費用に月額12か月分を足したものです。段階1は費用がほとんどかからず、事故の大半を防げるので、どのサイトでも最初に入れる価値があります。
損益は、壊れたときの損失と比べて考えます。問い合わせが月20件、1件500ユーロの価値があるサイトで、フォームが3日止まれば約1,000ユーロの機会を失います。アップロード画像が消えて作り直すなら、その工数も加わります。
13. よくある失敗
この記事で触れた Steam・GitLab.com・Knight Capital の事故は、それぞれ型1・6・9に当たります。ここでは、小さなサイトでよく見る失敗を並べます。
| 失敗 | 何が起きるか | 防ぎ方 |
|---|---|---|
| 除外を書き忘れた | アップロード画像が消える | 除外の一覧を手順書に固定 |
| ビルドの失敗を見ていない | 古いCSSのまま公開 | 終了コードで止める |
本番で env() を直接呼ぶ |
設定キャッシュ後に値が null | 設定ファイル経由で読む |
| ステージングの noindex | 本番が検索から外れる | 公開後に自動で確認 |
| 手元の未コミットの変更 | 意図しない変更が本番に出る | コミットから書き出して送る |
どの失敗も、仕組みを入れた後の「止まるか」「戻せるか」の確認を省いたときに起きます。
14. 日本と欧州で比べる
日本と欧州の両方でサイトを運用すると、デプロイの前提もいくつか変わります。優劣ではなく条件の違いです。
| 項目 | 日本でよくある形 | 欧州(オランダ)でよくある形 |
|---|---|---|
| サーバー | 共有のレンタルサーバー | 管理つきの VPS やクラウド |
| サーバーでの作業 | SSH は使えても道具が限られる | 配備ツールを入れやすい |
| 主な指針 | IPA の運用管理の20ヶ条 | NCSC の基本原則、ENISA の12ステップ |
| 漏えいの届出 | 個人情報保護委員会へ速報3〜5日 | 監督機関へ72時間以内 |
| 公開の時間帯 | 日本の営業時間 | 時差7〜8時間を考える |
共有のレンタルサーバーでは、Composer などの道具がサーバーにないことがあります。その場合は、手元か CI で本番と同じ版の依存を作り、まとめて送る形にします。
オランダと日本の時差は冬時間で8時間、夏時間で7時間です。オランダの朝10時の公開は、日本では夕方6時か5時になるため、どちらの側が公開後の確認をするかを先に決めておきます。秘密情報の漏えいに個人データが絡めば、欧州では GDPR 第33条により72時間以内の届出が要ることもあります。
15. ケースで考える(架空の3社)
ここでは架空の3社で、同じ考え方がどう違う答えになるかを見ます。
A社:日本の製造業の欧州向け英語サイト(静的なサイト)
更新は月2回ほどの静的なサイトで、段階1で足ります。rsync に除外・dry-run・削除の上限を付け、公開後に主要10ページを確かめます。戻すときは前のコミットを再ビルドして送り、30分以内が目安です。
B社:オランダの日本食材のネットショップ(CMS)
注文が1日30〜50件あるため段階3まで進め、ステージングで確かめ、公開の直前に DB のバックアップを取ります。公開は火曜か水曜の午前に限ります。
C社:日蘭2言語の士業事務所(Laravel のサイト)
記事の自動生成と手作業の修正が同じリポジトリに入るため、段階2で同時実行の制御と push 前の rebase を手順にしました。スモークテストに失敗したら自動でリンクを戻し、翌朝に日本側が Search Console を確かめます。
3社とも、最初に入れたのは段階1の確認と停止です。そこから、サイトの種類に合わせて足しています。
16. 導入の手順:4週間で進める
デプロイの安全対策は、4週間ほどで形にできます。週ごとに成果物を決めて進めます。
- 1週目:今の公開手順を書き出す。どのコマンドで、何を、どこへ送っているかを1枚にまとめる
- 1週目:本番にしかないファイルを洗い出す。設定、アップロード、サーバーで作るデータ、ログ(第4章の表)
- 2週目:スクリプトに
set -euo pipefailと送り元の確認を入れる - 2週目:dry-run の削除予定を見る工程と、削除の上限を入れる
- 3週目:リリースごとのディレクトリとリンクの切替に移す
- 3週目:スモークテストを入れ、失敗したら前の版へ戻す
- 4週目:同時実行の制御と、push 前の rebase を決める
- 4週目:わざと失敗させて試す。ビルドを壊す、送り元を空にする、戻す
最後の手順がいちばん大事です。止まるはずの仕組みが本当に止まるかは、失敗させてみないと分かりません。
17. やってはいけないこと
デプロイの自動化で避けたい設定と判断を並べます。
| やってはいけないこと | 理由 |
|---|---|
dry-run なしで --delete を使う |
消える一覧を見ないまま本番を揃える |
.env を転送対象に含める |
本番の設定を手元の値で上書きする |
| 失敗しても進むスクリプトにする | 壊れた状態のまま公開される |
| 実行中の本番公開を取り消す | 新旧のファイルが混在する |
| 構造とコードを1回で変える | ファイルを戻しても動かない |
| 強制 push で競合を解く | 相手の変更が消える |
| 公開後の確認を人の記憶に頼る | 誰も見ていない時間に壊れる |
自動化は、失敗を減らすものではなく、失敗に早く気づいて戻せるようにするものだと考えると、優先順位を決めやすくなります。
18. チェックリスト
公開の仕組みを作ったとき、変えたとき、四半期に1回、次の項目を確かめます。
- スクリプトの先頭に
set -euo pipefailがあり、大事な工程は失敗時にexit 1する - 転送の前に、送り元に必須のファイルがあるかを確かめている
-
--deleteを使うなら、dry-run の削除予定を確認し、--max-deleteで上限を置いている -
.env、アップロード、サーバーで作るデータ、ログが除外に入っている - 本体が公開ディレクトリの外にあり、本番の
APP_DEBUGがfalseになっている - 依存は lockfile から入れ、本番の PHP の版で解決している
- CSS と JS のファイル名に指紋があり、HTML は毎回確認される設定になっている
- 構造の変更は「足す→移す→消す」で分け、実行前にバックアップを取っている
- 本番への公開は同時に1本だけ走り、実行中のものを取り消さない
- 前の版へ1分以内に戻せ、その手順を実際に試した
- 公開直後に主要ページ・文字列・noindex・robots.txt を自動で確かめている
19. まとめ
- デプロイの事故は、ビルド・転送・切替・公開後の4段階に、9つの型で起きる
- いちばん防ぎやすく被害が大きいのは、想定外の削除と設定の上書き。dry-run・除外・削除の上限・送り元の確認で防ぐ
- 失敗したら止める。
set -euo pipefailと rsync の終了コードで、途中の状態を公開しない - キャッシュは、ファイル名の指紋と HTML の再確認で、古い表示と新旧の混在を防ぐ
- データベースの構造変更は、ファイルを戻しても戻らない。足す→移す→消すの順で、事前にバックアップ
- リリースごとのディレクトリとリンクの切替で、1分以内に戻せる形にする
- 公開直後の確認は自動にし、翌日の Search Console の確認は人が持つ
参考にした情報源
転送とスクリプト
- rsync(1) manual page — Samba:--delete・--dry-run・--max-delete・--delay-updates と終了コードの一覧
- The Set Builtin — GNU Bash Reference Manual:
-e・-u・pipefailの動き - rename(2) — Linux manual page:置き換えが原子的に行われること
- steam-for-linux issue #3671 — GitHub:空の変数による削除の事故
- git-push Documentation — Git:先に進んだブランチへの push が拒否されること
CI・リポジトリ・秘密情報
- Control the concurrency of workflows and jobs — GitHub Docs:同時実行の制御、取り消しと待ちの動き
- Managing environments for deployment — GitHub Docs:承認者、環境の秘密情報、プランごとの利用条件
- GitHub Actions billing — GitHub Docs:無料枠と1分あたりの料金
- About push protection — GitHub Docs:秘密情報を含む push の阻止
- Secrets Management Cheat Sheet — OWASP:秘密情報の分離と最小権限
ビルド・依存・フレームワーク
- npm ci — npm Docs:lockfile が必須で、食い違えば止まること
- Config: platform — Composer:本番の PHP の版での依存解決と注意点
- Supported Versions — PHP:系列ごとのサポート期限
- Deployment — Laravel:optimize と設定キャッシュ、APP_DEBUG、確認用ルート、ワーカーの再起動
- Database: Migrations — Laravel:本番での --force と --isolated
- Common recipe — Deployer:keep_releases の既定値(10)
キャッシュ・検索
- Prevent unnecessary network requests with the HTTP Cache — web.dev:指紋つき URL と長い max-age、HTML の再確認
- RFC 9111 HTTP Caching — IETF:Cache-Control の定義
- Pausing your online business — Google 検索セントラル:503 の期間と robots.txt の注意
- Block Search indexing with noindex — Google 検索セントラル:noindex の扱い
- HTTP status codes, network and DNS errors — Google 検索セントラル:5xx が続いたときの扱い
運用の考え方と事故報告
- DORA's software delivery performance metrics — DORA:5つの指標の定義と、目標値にする危うさ
- Canarying releases — Google SRE Workbook:カナリアの定義と進め方
- ParallelChange — Martin Fowler:足す・移す・消すの段階的な変更
- BlueGreenDeployment — Martin Fowler:2系統の入れ替え
- Postmortem of database outage of January 31 — GitLab:本番DBの削除とバックアップの失敗
- In the Matter of Knight Capital Americas LLC — SEC:8台中1台への配布漏れと損失
- SEC Charges Knight Capital With Violations of Market Access Rule — SEC:損失額と制裁金
- Helping our customers through the CrowdStrike outage — Microsoft:影響を受けた端末の推計
セキュリティの指針と届出
- Secure development and deployment guidance — NCSC(英国):安全な開発と配備の原則
- Cybersecurity guide for SMEs — ENISA:中小企業向けの12ステップ
- 安全なウェブサイトの運用管理に向けての20ヶ条 — IPA:ウェブサイトの運用管理
- Regulation (EU) 2016/679(GDPR) — EUR-Lex:第33条の72時間以内の届出
いずれも2026年10月31日に確認したものです。ツールの仕様・料金・サポート期限は変わるため、作業の前に公式のドキュメントで最新の情報を確認してください。費用と工数、戻すまでの時間の目安は DevNJ の実務上の目安で、サイトの規模と契約によって変わります。
よくある質問
- デプロイの自動化で、いちばん多い事故は何ですか?
- 小規模なサイトで多いのは、転送ツールの削除オプションで本番だけにあるファイル(アップロード画像や設定ファイル)を消してしまう事故と、ビルドや転送が途中で失敗したのに処理が止まらず、壊れた状態のまま公開される事故です。どちらも、削除予定の一覧を先に出す dry-run と、終了コードが0以外なら止める設定で大半を防げます。
- rsync の --delete は使わないほうが安全ですか?
- 使わないと、消したはずの古いファイルが本番に残り続け、それはそれで不具合や情報漏えいの原因になります。rsync の公式マニュアルは --delete を危険になり得ると明記したうえで、先に --dry-run で削除されるファイルを確かめるよう勧めています。除外の指定、--max-delete での上限、送り元が空でないかの確認を組み合わせて使うのが現実的です。
- ロールバックは、どう用意しておけばよいですか?
- 公開する版をリリースごとの別ディレクトリに置き、公開用のリンクだけを新しい版へ切り替える形にすると、戻すときはリンクを前の版に向け直すだけで済みます。Deployer という配備ツールは、既定で直近10版を残します。ただしデータベースの構造変更は、リンクを戻しても元に戻らないため、変更前のバックアップと、古いコードでも動く順番での変更が別に必要です。
- 小さな会社のサイトにもステージング環境は必要ですか?
- 問い合わせや注文を受けるサイト、PHPやデータベースを使うサイトでは用意したほうが安全です。静的なサイトなら、プルリクエストごとのプレビュー表示で代わりになることもあります。ステージングは検索結果に出ないよう、パスワードで保護します。noindex で隠す場合は、その設定が本番に持ち込まれないことを公開前チェックで確かめます。
- 公開後は、何をどのくらい確認すればよいですか?
- 直後に主要な5〜10ページの応答コードと決まった文字列を自動で確かめ、5〜30分はエラーログとフォームのテスト送信を見ます。翌日には Search Console でエラーや404の増加を確認します。Google は、503 を返す期間を1〜2日程度にとどめるよう案内しているため、長く止めないことも大切です。
- デプロイの安全対策には、どのくらいの費用がかかりますか?
- DevNJ の目安では、今あるスクリプトに確認と停止の仕組みを足す段階は初期6〜12時間、CIでのビルドとリリースの切替まで組む段階は16〜32時間、ステージングとデータベースの安全化まで含める段階は40〜80時間です。時間単価80ユーロで外注すると初期費用は480〜6,400ユーロ(1ユーロ175円換算で約8.4万〜112万円)、月額は0〜80ユーロの幅になります。
日本と欧州の両方で機能するサイトをお考えですか?
無料で相談する