rich@rich-vb-u24:~/pure-php-app$ cat nginx/practice.conf
server {
# 監聽 8080 埠並啟用 SSL 加密
listen 8080 ssl;
server_name _;
# 🔒 SSL 憑證與金鑰路徑(請根據實際存放位置修改)
ssl_certificate /etc/letsencrypt/live/longfutemple.duckdns.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/longfutemple.duckdns.org/privkey.pem;
# 🛡️ 建議加入的安全加密協定與演算法設定
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 1. 偵測並阻擋網址中包含常見的 LFI 路徑與 PHP 標籤
if ($request_uri ~* "(\.\./|boot\.ini|etc/passwd|win\.ini|<\?php)") {
return 403;
}
# 2. 偵測並阻擋 **User-Agent** 中包含 PHP 惡意代碼
if ($http_user_agent ~* "(<\?php|eval\(|base64_)") {
return 403;
}
# 🔒 3. 🛡️ 新增:資安個資防護!禁止任何人直接下載 .csv 志工名冊
location ~* \.csv$ {
deny all;
return 403;
}
root /var/www/htmlP;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
# 遇到 .php,丟給 php-practice 容器
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-practice:9000; # 🌟 精準指向 練習區 的 PHP 容器
fastcgi_index index.php;
include fastcgi_params;
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # php ext file 強制走容器的/var/www/html 路徑
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
從你執行的測試結果來看,掛載完全正常(Nginx 容器內確實看得到檔案),且 Nginx 的語法測試也完全通過。
既然檔案在、設定也對,卻依然噴出 404,那問題就只剩下最後一個最隱蔽、也最常見的 Docker 跨容器地雷:「你的 Nginx 容器有讀到檔案,但 php-practice 容器可能根本找不到檔案!」
請注意這行關鍵設定:
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
這行是告訴 php-practice 容器:「請去執行你裡面的 /var/www/html/volunteer_survey.php」。
如果 php-practice 容器內部的 /var/www/html 資料夾其實是空的,或者掛載錯了,PHP 就會對 Nginx 回報找不到檔案,而 Nginx 就會一臉無辜地對瀏覽器顯示「404 Not Found」(這個 404 是 PHP 拋出來的,不是 Nginx 的 404)。
php-practice 容器內部到底有沒有檔案?請在終端機輸入這行指令,直接看 PHP 容器內部:
docker exec -it php-for-practice ls -la /var/www/html
(注意:要檢查的是 php-for-practice 容器,也就是你的 PHP 服務)
docker-compose.yml 中幫 php-practice 設定的 ./practice-data:/var/www/html 掛載,因為某些原因沒有成功同步到運作中的容器。Docker Compose 有時候在修改了 Volume 掛載路徑後,如果是用 nginx -s reload,只有 Nginx 刷新,但 PHP 容器依然抓著舊的容器實例(Instance)。
請直接執行以下強制重組命令,這會徹底清除 Docker 容器殘留的舊路徑快取:
# 1. 徹底停止並刪除舊容器(資料不會不見,因為檔案在你的主機上)
docker compose down# 2. 強制重新編譯、建立並啟動所有容器
docker compose up -d --build --force-recreate