😊
Django + Nginx環境で静的ファイルが404エラーになる問題の解決方法
Django + Nginx環境で静的ファイルが404エラーになる問題の解決方法
はじめに
DjangoアプリケーションをNginxでリバースプロキシ配信する際、静的ファイル(CSS、JavaScript、画像など)が404エラーになることがあります。本記事では、この問題の原因と解決方法を段階的に解説します。
問題の症状
以下のようなDjango 404エラーページが表示される:
Page not found (404)
Request Method: GET
Request URL: http://example.com/static/logo/logo_image.png
Using the URLconf defined in config.urls, Django tried these URL patterns, in this order:
1. [name='index']
2. blog/ [name='blog_list']
3. blog/<int:pk>/ [name='blog_detail']
...
The current path, static/logo/logo_image.png, didn't match any of these.
環境構成
- サーバー: Linux (Amazon Linux等)
- Webサーバー: Nginx
- アプリケーション: Django
-
静的ファイルの場所:
/path/to/project/app_name/static/
原因の分析
1. 複数のServerブロックの競合
Nginxでは複数のserver
ブロックが同じポートをlistenしている場合、最初に見つけたものがデフォルトとして使用されます。
# /etc/nginx/nginx.conf にデフォルトのserverブロック
server {
listen 80;
server_name _;
root /usr/share/nginx/html; # ここが優先される
...
}
# /etc/nginx/conf.d/myapp.conf のカスタム設定
server {
listen 80; # 同じポートで競合
location /static/ {
alias /path/to/project/app_name/static/;
}
...
}
2. ディレクトリアクセス権限の問題
Nginxのワーカープロセスが静的ファイルディレクトリにアクセスできない場合があります。
解決手順
Step 1: Nginxの設定状況を確認
現在の設定を確認します:
sudo nginx -T | grep -B 5 -A 15 "server {"
Step 2: デフォルトServerブロックの無効化
/etc/nginx/nginx.conf
内のデフォルトserverブロックをコメントアウトします:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
sudo vi /etc/nginx/nginx.conf
以下の部分をコメントアウト:
# server {
# listen 80;
# listen [::]:80;
# server_name _;
# root /usr/share/nginx/html;
#
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /404.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
Step 3: カスタム設定ファイルの作成
/etc/nginx/conf.d/myapp.conf
を作成します:
upstream django_app {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name _;
# 静的ファイルを直接配信
location /static/ {
alias /path/to/project/app_name/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Djangoアプリケーションへのプロキシ
location / {
proxy_pass http://django_app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Step 4: ディレクトリ権限の設定
Nginxワーカープロセスがファイルにアクセスできるよう権限を設定します:
# Nginxユーザーの確認
ps aux | grep nginx | head -2
# ディレクトリパス全体に実行権限を付与
sudo chmod 755 /home/username/
sudo chmod 755 /path/to/project/
sudo chmod 755 /path/to/project/app_name/
sudo chmod 755 /path/to/project/app_name/static/
sudo chmod 755 /path/to/project/app_name/static/images/
# ファイルに読み取り権限を付与
sudo chmod 644 /path/to/project/app_name/static/images/*
Step 5: 設定の適用とテスト
# 設定ファイルのテスト
sudo nginx -t
# Nginxの再読み込み
sudo systemctl reload nginx
# 動作確認
curl -I http://localhost/static/images/logo.png
トラブルシューティング
404エラーが続く場合
設定が正しく読み込まれているか確認:
sudo nginx -T | grep -A 10 "location /static/"
403 Forbiddenエラーの場合
権限問題の可能性があります:
# Nginxユーザーでのアクセステスト
sudo -u nginx ls -la /path/to/project/app_name/static/
# エラーログの確認
sudo tail -10 /var/log/nginx/error.log
パス設定の間違い
location /static/
とalias
のパスが正しく対応しているか確認:
# ❌ 間違い: 末尾スラッシュの不一致
location /static { # スラッシュなし
alias /path/to/static/; # スラッシュあり
}
# ✅ 正しい: 末尾スラッシュを統一
location /static/ { # スラッシュあり
alias /path/to/static/; # スラッシュあり
}
WhiteNoiseとの使い分け
現在の推奨構成(Nginx + WhiteNoise併存)
実際の運用では、以下のような構成が安全で効率的です:
server {
listen 80;
# Nginxで静的ファイルを直接配信(高速)
location /static/ {
alias /path/to/project/app_name/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://django_app;
# プロキシ設定
}
}
# settings.py(WhiteNoiseも残す)
MIDDLEWARE = [
"whitenoise.middleware.WhiteNoiseMiddleware", # 残しておく
# ...
]
STATIC_ROOT = "/path/to/static/"
この構成のメリット:
- Nginxが優先: 静的ファイルはNginxが高速配信
- フォールバック: Nginx設定にミスがあってもWhiteNoiseが動作
- 開発環境対応: Nginxなしの環境でもWhiteNoiseが機能
WhiteNoiseのみで配信する場合
Nginxでの静的ファイル配信設定を削除し、すべてDjangoに委ねる方法:
server {
listen 80;
# 静的ファイル設定なし
location / {
proxy_pass http://django_app;
# プロキシ設定
}
}
この場合、すべての静的ファイルリクエストがDjangoに渡され、WhiteNoiseが処理します。
まとめ
Django + Nginx環境での静的ファイル404エラーの主な原因は:
- Serverブロックの競合: デフォルト設定が優先される
- 権限問題: Nginxユーザーがファイルにアクセスできない
- パス設定ミス: locationとaliasの不一致
これらを順序立てて解決することで、静的ファイルが正常に配信されるようになります。特に権限設定は見落としがちなポイントなので、注意深く確認することが重要です。
Discussion