この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: プログラムが本番サーバーで反映されない場合の対処法
SEOタイトル: 本番サーバーでコード変更が反映されない(キャッシュ・OPcache・LB・CDN の切り分け)

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li>原因の 9 割は<strong>キャッシュ</strong>。Laravel: <code>php artisan optimize:clear</code>、PHP: OPcache reset、ブラウザ/CDN: バスター付与</li><li>Laravel: <strong><code>config:clear</code> / <code>cache:clear</code> / <code>view:clear</code> / <code>route:clear</code></strong> をまとめて</li><li><strong>OPcache</strong> は <code>opcache_reset()</code> または <code>php-fpm reload</code> で再評価</li><li><strong>LB 配下</strong>で「特定ユーザーだけ古い」なら、ロードバランサ配下の<strong>一部サーバだけデプロイ漏れ</strong>を疑う</li><li><strong>CDN / Cloudflare</strong>: ダッシュボードで Purge Everything、または <code>?v=20260517</code> でキャッシュバスター</li><li>ブラウザキャッシュ: <code>Ctrl+F5</code> / DevTools の「Disable cache」、本番では HTML に <code>Cache-Control</code> ヘッダ</li></ul></td></tr></table>
<h2>切り分けフロー</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>質問</th><th>YES なら</th><th>NO なら</th></tr></thead>
<tbody>
<tr><td>1. 自分の手元(開発機)では反映済?</td><td>本番固有問題(下へ)</td><td>コード変更/コミット漏れを疑う</td></tr>
<tr><td>2. サーバーに pull / デプロイされている?</td><td>3 へ</td><td>git pull / デプロイ再実行</td></tr>
<tr><td>3. PHP / Node / Java のプロセスをリスタートした?</td><td>4 へ</td><td>opcache reset / php-fpm reload / pm2 restart</td></tr>
<tr><td>4. ブラウザを Ctrl+F5 した?</td><td>5 へ</td><td>ブラウザキャッシュ</td></tr>
<tr><td>5. CDN / プロキシ経由?</td><td>CDN purge</td><td>サーバー内キャッシュ深掘り</td></tr>
<tr><td>6. LB で複数台ある?</td><td>各サーバーの版数確認</td><td>—</td></tr>
</tbody>
</table>

<h2>Laravel: まず全キャッシュをクリア</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash">cd /var/www/html

# 全部まとめてクリア
php artisan optimize:clear

# 個別実行
php artisan config:clear      # config/ 配下のキャッシュ
php artisan cache:clear       # Cache::put した内容
php artisan view:clear        # コンパイル済 Blade
php artisan route:clear       # ルートキャッシュ
php artisan event:clear       # イベントキャッシュ

# 本番では config / route / view はキャッシュした方が高速 → 再生成
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache</code></pre>
<h2>OPcache をリセット</h2>

<p>PHP は本番では<strong>OPcache</strong>でコンパイル済みコードをメモリ保持しているため、ファイル更新後すぐに反映されないことがあります。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash"># 方法1: PHP-FPM をリロード(無停止)
sudo systemctl reload php8.2-fpm
# OPcache のメモリがクリアされる

# 方法2: 専用エンドポイントで opcache_reset()
# routes/web.php 等に(IP 制限必須):
# Route::get(&apos;/opcache-reset&apos;, function () {
#     if (request()->ip() !== &apos;127.0.0.1&apos;) abort(403);
#     opcache_reset();
#     return &apos;reset&apos;;
# });

# 方法3: cachetool(推奨)
composer global require gordalina/cachetool
cachetool opcache:reset --fcgi=/run/php/php8.2-fpm.sock

# OPcache の状態を確認
cachetool opcache:status --fcgi=/run/php/php8.2-fpm.sock</code></pre>
<h2>php.ini で「自動再評価」設定</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-ini">; 本番推奨設定
opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 20000

; ファイル変更を 60 秒ごとに自動検出(開発機向け)
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60

; 完全停止して再起動でしか反映しない(本番の最高速設定)
opcache.validate_timestamps = 0
; → デプロイのたびに php-fpm reload が必須</code></pre>
<h2>ブラウザキャッシュ対処</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- HTML ファイル自体をキャッシュさせない -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">

<!-- 静的アセットはバージョン付与 -->
<link rel="stylesheet" href="/css/app.css?v=20260517">
<script src="/js/app.js?v=20260517"></script>

<!-- Laravel Mix / Vite の場合は自動バスター -->
<link rel="stylesheet" href="{{ mix(&apos;css/app.css&apos;) }}">    <!-- ?id=ハッシュ -->
@vite(&apos;resources/css/app.css&apos;)                              <!-- ハッシュ込ファイル名 --></code></pre>
<h2>Nginx の Cache-Control 設定</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-nginx"># HTML は短いキャッシュ
location ~ \.(html|htm)$ {
    add_header Cache-Control "no-cache, must-revalidate";
}

# 画像/CSS/JS(ハッシュ付ファイル名前提)は長期キャッシュ
location ~* \.(css|js|jpg|jpeg|png|webp|svg|woff2)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# プロキシキャッシュを使っている場合は purge も
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app:10m;
# 緊急時:
# rm -rf /var/cache/nginx/*
# systemctl reload nginx</code></pre>
<h2>CDN (Cloudflare 等) のパージ</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash"># Cloudflare API でパージ
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data &apos;{"purge_everything":true}&apos;

# 特定 URL だけ
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data &apos;{"files":["https://example.com/css/app.css"]}&apos;

# Cloudflare ダッシュボード → Caching → Configuration → Purge Everything</code></pre>
<h2>ロードバランサ配下の「特定ユーザーだけ古い」</h2>

<p>「自分は最新、同僚は古い」「リロードすると最新と古いが交互に出る」というときは、<strong>LB の後ろの一部サーバだけデプロイ漏れ</strong>を疑います。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash"># 各サーバの版数を返すエンドポイントを用意
# routes/web.php:
# Route::get(&apos;/_version&apos;, fn() => gethostname() . &apos;:&apos; . exec(&apos;git rev-parse --short HEAD&apos;));

# クライアントから連打して全サーバを叩く
for i in {1..20}; do curl https://example.com/_version; echo; done
# web01:abc1234
# web02:def5678   ← これだけ違うコミット = デプロイ漏れ
# web01:abc1234
# ...

# デプロイ漏れサーバで個別実行
ssh web02 &apos;cd /var/www/html && git pull && php artisan optimize:clear && systemctl reload php8.2-fpm&apos;</code></pre>
<h2>Java / Node / Python の場合</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>言語</th><th>反映に必要な操作</th></tr></thead>
<tbody>
<tr><td>Java (Tomcat)</td><td>新しい .war をデプロイ → <code>systemctl restart tomcat</code> / 自動 reload 設定</td></tr>
<tr><td>Java (Spring Boot)</td><td>jar 入替 → systemd で restart</td></tr>
<tr><td>Node.js</td><td><code>pm2 reload</code> / <code>pm2 restart all</code></td></tr>
<tr><td>Python (Django/Flask)</td><td><code>systemctl reload gunicorn</code> / uwsgi reload</td></tr>
<tr><td>Python (Lambda)</td><td>関数を再デプロイ(更新後即時反映)</td></tr>
</tbody>
</table>

<h2>FAQ</h2>

<p><strong>Q: <code>php artisan optimize:clear</code> しても反映されない</strong><br />
A: OPcache が残っている可能性大。<code>systemctl reload php8.2-fpm</code> を必ず併用。</p>

<p><strong>Q: 開発機では動くのに本番だけ古い</strong><br />
A: 本番だけ config キャッシュが効いている。<code>php artisan config:clear && php artisan config:cache</code>。</p>

<p><strong>Q: 画像/CSS だけ古い</strong><br />
A: 静的アセットは長期 Cache-Control が効いている。バージョンクエリ付与 or Vite/Mix のハッシュファイル名運用に。</p>