Nginx配置PHP访问问题排查

根据最新的测试结果,我们发现容器内缺少 php-cgi 命令,这解释了为什么 PHP-FPM 无法正常处理请求。以下是终极解决方案:


🔧 终极修复步骤

1. 安装 php-cgi

在容器内执行:

1
apt-get update && apt-get install -y php7.4-cgi

2. 验证 PHP-FPM 配置

确认 /etc/php/7.4/fpm/pool.d/www.conf 包含:

1
2
3
4
listen = 127.0.0.1:9000
user = www-data
group = www-data
security.limit_extensions = .php

3. 强制测试 FastCGI

1
2
3
SCRIPT_FILENAME=/var/www/html/index.php \
REQUEST_METHOD=GET \
php-cgi -b 127.0.0.1:9000

4. 修改 Nginx 配置

确保 /etc/nginx/conf.d/default.conf 包含:

1
2
3
4
5
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

5. 重启服务

1
2
service nginx restart
service php7.4-fpm restart

📌 验证方法

  1. 测试 FastCGI

    1
    2
    # 在容器内执行
    SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET php-cgi -b 127.0.0.1:9000
  2. 测试 Nginx

    1
    curl -v "http://localhost:8085/index.php"
  3. 检查日志

    1
    tail -f /var/log/nginx/error.log /var/log/php7.4-fpm.log

🚨 常见问题解决

问题 解决方案
php-cgi: command not found 安装 php7.4-cgi
FastCGI 通信失败 检查 fastcgi_pass 地址
文件权限问题 chown -R www-data:www-data /var/www/html

请先安装 php-cgi 后继续测试,如果仍有问题,请提供:

  1. apt-get install php7.4-cgi 的输出
  2. 安装后 php-cgi -v 的结果
  3. 新的测试结果

时间: 2025-04-02T22:14:49


👤 用户

帮我看下配置,我好像不能访问php,会直接下载php文件
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
    try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_index index.php;
    
    # 安全设置
    try_files $uri =404;
    
    # 性能优化
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
}

# 禁止访问敏感文件
location ~ /(\.ht|vendor|composer\.json) {
    deny all;
}

}

时间: 2025-04-02T01:43:35


🤖 DeepSeek (deepseek-chat)

你的 Nginx 配置看起来基本正确,但 PHP 文件被直接下载而不是执行,通常是因为 PHP-FPM 没有正确处理请求。以下是可能的原因和解决方案:

常见问题排查

  1. PHP-FPM 服务未运行

    1
    systemctl status php-fpm  # 或 php7.x-fpm/php8.x-fpm

    如果没有运行,启动它:

    1
    systemctl start php-fpm
  2. fastcgi_pass 地址/端口不正确

    • 确认 PHP-FPM 监听的是 127.0.0.1:9000
    1
    netstat -tulnp | grep php
    • 如果是 Unix socket 方式(常见于较新版本),需要修改为:
      1
      fastcgi_pass unix:/var/run/php/phpX.X-fpm.sock;
  3. 缺少必要的 fastcgi 参数
    虽然你的配置中有 SCRIPT_FILENAME,但建议补充完整:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_intercept_errors on;
    fastcgi_index index.php;
    }
  4. 文件权限问题
    确保 Nginx 用户(通常是 www-datanginx)有权限读取 PHP 文件:

    1
    2
    chown -R www-data:www-data /var/www/html
    chmod -R 755 /var/www/html

完整建议配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
# 使用实际PHP版本对应的socket
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;

fastcgi_intercept_errors on;
fastcgi_index index.php;

# 安全设置
try_files $uri =404;
}

location ~ /(\.ht|vendor|composer\.json) {
deny all;
}
}

测试步骤

  1. 创建一个测试文件 /var/www/html/info.php

    1
    <?php phpinfo(); ?>
  2. 重启服务:

    1
    systemctl restart nginx php-fpm
  3. 访问 http://localhost/info.php 应该显示 PHP 信息页面

如果问题仍然存在,请检查:

  • Nginx 错误日志:tail -f /var/log/nginx/error.log
  • PHP-FPM 日志:journalctl -u php-fpm -f

时间: 2025-04-02T01:43:35


👤 用户

我是在docker 下运行的

时间: 2025-04-02T01:45:13


🤖 DeepSeek (deepseek-chat)

在 Docker 环境下遇到 Nginx 直接下载 PHP 文件而不是执行的问题,通常是因为 PHP-FPM 服务未正确配置Nginx 与 PHP-FPM 之间的通信问题。以下是解决方案:


🛠 可能的原因及解决方案

1. PHP-FPM 容器未运行或未连接

  • 检查 PHP-FPM 容器是否正在运行

    1
    docker ps

    确保你的 php-fpm 容器(如 php, php-fpm 等)正在运行。

  • 确保 Nginx 能访问 PHP-FPM

    • 如果 PHP-FPM 和 Nginx 在同一个 Docker 网络,确保 fastcgi_pass 指向正确的服务名(如 php:9000)。
    • 示例:
      1
      fastcgi_pass php:9000;  # 假设 PHP-FPM 服务名为 "php"

2. Nginx 配置错误

  • 确保 fastcgi_pass 指向正确的 PHP-FPM 地址

    • 如果 PHP-FPM 和 Nginx 在同一个 Docker 网络,通常用服务名(如 php:9000)。
    • 如果 PHP-FPM 在宿主机上,用 host.docker.internal:9000(Mac/Windows)或 172.17.0.1:9000(Linux Docker 默认桥接网络)。
  • 正确的 location ~ \.php$ 配置

    1
    2
    3
    4
    5
    6
    7
    location ~ \.php$ {
    fastcgi_pass php:9000; # 或 host.docker.internal:9000
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_index index.php;
    try_files $uri =404;
    }

3. PHP-FPM 未监听 9000 端口

  • 检查 PHP-FPM 配置(通常是 /usr/local/etc/php-fpm.d/www.conf):
    1
    listen = 9000  # 确保 PHP-FPM 监听 9000 端口
    或者如果是 Unix socket:
    1
    listen = /var/run/php-fpm.sock
    然后在 Nginx 配置中:
    1
    fastcgi_pass unix:/var/run/php-fpm.sock;

4. 文件路径问题

  • 确保 $document_root 路径正确
    • 在 Docker 中,Nginx 和 PHP-FPM 的 root 路径必须一致(如 /var/www/html)。
    • 检查 docker-compose.ymlDockerfile 是否正确挂载了代码目录。

5. Docker 网络问题

  • 确保 Nginx 和 PHP-FPM 在同一个 Docker 网络
    1
    docker network inspect <network_name>
    如果它们不在同一个网络,Nginx 无法访问 PHP-FPM。

🐳 Docker 示例配置

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: "3.8"

services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./html:/var/www/html
depends_on:
- php
networks:
- app-network

php:
image: php:8.2-fpm
volumes:
- ./html:/var/www/html
networks:
- app-network

networks:
app-network:
driver: bridge

nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass php:9000; # 使用 PHP-FPM 的服务名
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
try_files $uri =404;
}
}

🔍 调试步骤

  1. 进入 Nginx 容器检查连接

    1
    2
    3
    docker exec -it nginx-container sh
    apk add curl # 如果 Alpine 镜像
    curl php:9000 # 测试是否能连接 PHP-FPM
  2. 检查 PHP-FPM 日志

    1
    docker logs php-container
  3. 检查 Nginx 错误日志

    1
    docker logs nginx-container
  4. 测试 PHP 文件

    • ./html/index.php 写入:
      1
      <?php phpinfo(); ?>
    • 访问 http://localhost,应该显示 PHP 信息页面。

最终解决方案

  1. 确保 PHP-FPM 运行

    1
    docker-compose up -d php
  2. 确保 fastcgi_pass 正确

    • 如果 PHP-FPM 服务名是 php,用 php:9000
    • 如果 PHP-FPM 在宿主机,用 host.docker.internal:9000
  3. 确保 Nginx 和 PHP-FPM 共享相同的代码卷

  4. 重启服务

    1
    docker-compose restart nginx php

如果仍然有问题,请提供:

  • docker-compose.yml
  • nginx.conf
  • docker ps 输出
  • Nginx 和 PHP-FPM 的日志。

时间: 2025-04-02T01:45:13


👤 用户

root@d80d5cddc819:/var/www/html# which php
/usr/bin/php
root@d80d5cddc819:/var/www/html# which php-fpm
root@d80d5cddc819:/var/www/html# systemctl status php-fpm
System has not been booted with systemd as init system (PID 1). Can’t operate.
Failed to connect to bus: Host is down
root@d80d5cddc819:/var/www/html# systemctl start php-fpm
System has not been booted with systemd as init system (PID 1). Can’t operate.
Failed to connect to bus: Host is down
root@d80d5cddc819:/var/www/html#

时间: 2025-04-02T20:54:11


🤖 DeepSeek (deepseek-chat)

从你的输出可以看出,你在 Docker 容器内尝试运行 systemctl,但 Docker 容器默认不使用 systemd(PID 1 不是 systemd),所以 systemctl 命令无法工作。

问题分析

  1. php-fpm 未安装或未运行

    • which php-fpm 返回空,说明 php-fpm 可能未安装。
    • 即使安装了,由于 Docker 容器没有 systemd,你需要手动启动 php-fpm
  2. Nginx 无法处理 PHP 请求

    • 因为 php-fpm 没有运行,Nginx 无法处理 .php 文件,导致直接下载。

解决方案

1. 检查是否安装了 php-fpm

1
2
apt update
apt list --installed | grep php-fpm

如果没有安装,安装它:

1
apt install php-fpm -y

2. 手动启动 php-fpm

由于 systemctl 在 Docker 容器内不可用,你需要直接运行 php-fpm

1
php-fpm -D  # -D 表示以守护进程方式运行

检查是否运行:

1
ps aux | grep php-fpm

如果看到 php-fpm 进程,说明它正在运行。


3. 修改 Nginx 配置

确保 fastcgi_pass 指向正确的 PHP-FPM 地址:

1
2
3
4
5
6
7
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 如果 PHP-FPM 在同一个容器
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
try_files $uri =404;
}

如果 PHP-FPM 在另一个容器(推荐),用服务名:

1
fastcgi_pass php:9000;  # 假设 PHP-FPM 的服务名是 "php"

4. 测试 PHP 处理

创建一个测试文件 /var/www/html/info.php

1
<?php phpinfo(); ?>

访问 http://localhost/info.php,应该显示 PHP 信息页面。


推荐 Docker 运行方式

如果你使用 docker-compose,建议:

  1. 分离 Nginx 和 PHP-FPM 容器(推荐)
  2. 确保 php-fpm 在单独的容器运行
  3. 使用 depends_on 确保 PHP-FPM 先启动

示例 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: "3.8"

services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./html:/var/www/html
depends_on:
- php

php:
image: php:8.2-fpm
volumes:
- ./html:/var/www/html

Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location ~ \.php$ {
fastcgi_pass php:9000; # 指向 PHP-FPM 服务名
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
}
}

总结

  1. 不要在 Docker 容器内使用 systemctl,改用直接运行命令(如 php-fpm -D)。
  2. 确保 php-fpm 已安装并运行
  3. 检查 fastcgi_pass 配置是否正确127.0.0.1:9000php:9000)。
  4. 推荐使用 docker-compose 分离 Nginx 和 PHP-FPM

如果仍有问题,请提供:

  • docker-compose.yml(如果有)
  • nginx.conf 完整配置
  • docker ps 输出
  • docker logs <container_name> 日志

时间: 2025-04-02T20:54:11


👤 用户

root@d80d5cddc819:/var/www/html# service php7.4-fpm start
root@d80d5cddc819:/var/www/html# which php-fpm
root@d80d5cddc819:/var/www/html# which php7.4-fpm
root@d80d5cddc819:/var/www/html#

时间: 2025-04-02T20:56:08


🤖 DeepSeek (deepseek-chat)

从你的命令输出来看,php-fpm 似乎没有正确安装或无法找到可执行文件。以下是完整的解决方案:


1. 确认 PHP-FPM 是否安装

运行以下命令检查是否安装了 php-fpm

1
2
apt update
apt list --installed | grep php

如果没有 php-fpm,则需要安装它:

1
apt install php-fpm -y

(如果你的 PHP 版本是 7.4,可以指定安装 php7.4-fpm


2. 手动启动 PHP-FPM

由于 Docker 容器没有 systemd,不能使用 systemctlservice 命令。
你需要手动启动 php-fpm

1
php-fpm -D  # 以守护进程方式运行

或者(如果安装了特定版本):

1
php7.4-fpm -D

检查是否运行:

1
ps aux | grep php-fpm

如果看到类似 php-fpm: master process 的进程,说明它正在运行。


3. 检查 PHP-FPM 监听方式

默认情况下,PHP-FPM 可能监听:

  • TCP 端口(如 127.0.0.1:9000
  • Unix Socket(如 /var/run/php/php7.4-fpm.sock

运行以下命令查看:

1
netstat -tulnp | grep php

1
ls /var/run/php/

如果使用 Unix Socket,Nginx 配置应该是:

1
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

如果使用 TCP 端口,Nginx 配置应该是:

1
fastcgi_pass 127.0.0.1:9000;

4. 检查 Nginx 配置

确保 location ~ \.php$ 正确指向 PHP-FPM:

1
2
3
4
5
6
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # 或 127.0.0.1:9000
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
}

然后重启 Nginx:

1
nginx -s reload

5. 测试 PHP 处理

创建测试文件 /var/www/html/info.php

1
<?php phpinfo(); ?>

访问 http://localhost/info.php,应该显示 PHP 信息页面。


6. 如果仍然无法运行

可能的问题

  • PHP-FPM 未正确安装 → 重新安装 php-fpm
  • Nginx 和 PHP-FPM 不在同一个容器 → 使用 docker-compose 管理多容器。
  • 文件权限问题 → 确保 /var/www/html 可读:
    1
    chmod -R 755 /var/www/html

推荐使用 Docker Compose

如果你没有使用 docker-compose,建议采用以下架构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
version: "3.8"
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./html:/var/www/html
depends_on:
- php

php:
image: php:7.4-fpm
volumes:
- ./html:/var/www/html

这样 PHP-FPM 会自动运行,Nginx 只需配置 fastcgi_pass php:9000;


总结

  1. 安装 php-fpmapt install php-fpm)。
  2. 手动启动 php-fpmphp-fpm -D)。
  3. 检查 PHP-FPM 监听方式netstatls /var/run/php/)。
  4. 调整 Nginx 的 fastcgi_passunix:/var/run/php/php7.4-fpm.sock127.0.0.1:9000)。
  5. 测试 info.php 是否正常显示。

如果仍有问题,请提供:

  • nginx.conf 完整内容
  • docker ps 输出
  • docker logs <容器名> 日志

时间: 2025-04-02T20:56:08


👤 用户

root@d80d5cddc819:/var/www/html# ps aux | grep php-fpm
root 15 0.0 0.3 55820 7144 ? Ss 18:15 0:00 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
www-data 16 0.0 0.3 55820 6608 ? S 18:15 0:00 php-fpm: pool www
www-data 17 0.0 0.3 55820 6608 ? S 18:15 0:00 php-fpm: pool www
root 346 0.0 0.0 8164 716 pts/0 S+ 20:56 0:00 grep –color=auto php-fpm
root@d80d5cddc819:/var/www/html#

时间: 2025-04-02T20:57:08


🤖 DeepSeek (deepseek-chat)

从你的 ps aux | grep php-fpm 输出可以看出,PHP-FPM 正在运行(有一个 master 进程和两个 worker 进程)。但 Nginx 仍然直接下载 PHP 文件,说明 Nginx 和 PHP-FPM 之间的通信可能有问题。以下是排查和解决方案:


1. 检查 PHP-FPM 监听方式

运行以下命令,确认 PHP-FPM 是监听 Unix Socket 还是 TCP 端口

1
cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen

可能的结果

  • Unix Socket(默认):
    1
    listen = /run/php/php7.4-fpm.sock
    ➔ Nginx 配置应为:
    1
    fastcgi_pass unix:/run/php/php7.4-fpm.sock;
  • TCP 端口
    1
    listen = 127.0.0.1:9000
    ➔ Nginx 配置应为:
    1
    fastcgi_pass 127.0.0.1:9000;

2. 检查 Nginx 配置

确保 location ~ \.php$fastcgi_pass 与 PHP-FPM 的 listen 一致。
完整示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location ~ \.php$ {
# 根据 PHP-FPM 的监听方式选择一种:
fastcgi_pass unix:/run/php/php7.4-fpm.sock; # Unix Socket
# fastcgi_pass 127.0.0.1:9000; # TCP 端口

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
try_files $uri =404;
}
}

3. 检查文件权限

PHP-FPM 的 worker 进程(www-data 用户)需要能读取 PHP 文件:

1
2
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html

4. 测试 PHP-FPM 是否能处理请求

手动发送一个请求到 PHP-FPM(假设监听 9000 端口):

1
2
apt install curl
curl -v "http://localhost/index.php"

如果返回 502 Bad Gateway 或直接下载文件,说明 Nginx 和 PHP-FPM 通信失败。


5. 查看日志

Nginx 错误日志

1
tail -f /var/log/nginx/error.log

常见错误:

  • Connection refused to unix:/run/php/php7.4-fpm.sock → PHP-FPM 未运行或路径错误。
  • Primary script unknownSCRIPT_FILENAME 配置错误。

PHP-FPM 日志

1
tail -f /var/log/php7.4-fpm.log

6. 最终解决方案

如果使用 Unix Socket

  1. 确保 Socket 文件存在:
    1
    ls -l /run/php/php7.4-fpm.sock
  2. 如果不存在,重启 PHP-FPM:
    1
    killall php-fpm && php-fpm -D
  3. 确保 Nginx 有权限访问 Socket:
    1
    chown www-data:www-data /run/php/php7.4-fpm.sock

如果使用 TCP 端口

  1. 检查 PHP-FPM 是否监听 9000
    1
    netstat -tulnp | grep 9000
  2. 如果未监听,修改 /etc/php/7.4/fpm/pool.d/www.conf
    1
    listen = 127.0.0.1:9000
    然后重启 PHP-FPM:
    1
    killall php-fpm && php-fpm -D

7. 快速测试

创建一个测试文件 /var/www/html/info.php

1
<?php phpinfo(); ?>

访问 http://localhost/info.php,应该显示 PHP 信息页面。


总结

  1. 确认 PHP-FPM 监听方式unix:/run/php/php7.4-fpm.sock127.0.0.1:9000)。
  2. 调整 Nginx 的 fastcgi_pass 保持一致。
  3. 检查权限(确保 www-data 可读 /var/www/html)。
  4. 查看日志/var/log/nginx/error.log/var/log/php7.4-fpm.log)。

如果仍有问题,请提供:

  • cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
  • ls -l /run/php/
  • tail -n 20 /var/log/nginx/error.log

时间: 2025-04-02T20:57:08


👤 用户

root@d80d5cddc819:/var/www/html# cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
; - ‘listen’ (unixsocket)
; ‘ip.add.re.ss:port’ - to listen on a TCP socket to a specific IPv4 address on
; ‘[ip:6:addr:ess]:port’ - to listen on a TCP socket to a specific IPv6 address on
; ‘port’ - to listen on a TCP socket to all addresses
; ‘/path/to/unix/socket’ - to listen on a unix socket.
listen = 127.0.0.1:9000
; Set listen(2) backlog.
;listen.backlog = 511
listen.owner = www-data
listen.group = www-data
;listen.mode = 0660
; When set, listen.owner and listen.group are ignored
;listen.acl_users =
;listen.acl_groups =
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
;listen.allowed_clients = 127.0.0.1
; listen queue - the number of request in the queue of pending
; connections (see backlog in listen(2));
; max listen queue - the maximum number of requests in the queue
; listen queue len - the size of the socket queue of pending connections;
; listen queue: 0
; max listen queue: 1
; listen queue len: 42

时间: 2025-04-02T20:58:22


🤖 DeepSeek (deepseek-chat)

根据你的 www.conf 配置,PHP-FPM 正在监听 TCP 端口 127.0.0.1:9000,但 Nginx 仍然无法正确处理 PHP 文件。以下是完整的解决方案:


🔧 关键修复步骤

1. 确认 Nginx 配置匹配 PHP-FPM 的监听方式

修改 Nginx 配置中的 fastcgi_pass 为:

1
2
3
4
5
6
7
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 必须与 PHP-FPM 的 listen 一致
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
try_files $uri =404;
}

2. 检查 PHP-FPM 是否真正在监听 9000 端口

运行以下命令验证:

1
netstat -tulnp | grep 9000

预期输出应包含:

1
tcp    0    0 127.0.0.1:9000    0.0.0.0:*    LISTEN    <PID>/php-fpm

如果没有输出,说明 PHP-FPM 未正确启动,需重启:

1
killall php-fpm && php-fpm -D

3. 解除 listen.allowed_clients 限制(关键)

你的配置中有一行注释:

1
;listen.allowed_clients = 127.0.0.1

取消注释并确保包含 Nginx 的 IP(如果是 Docker 需用容器 IP):

1
listen.allowed_clients = 127.0.0.1

然后重启 PHP-FPM:

1
killall php-fpm && php-fpm -D

4. 检查防火墙/SELinux(Docker 通常无需)

如果是宿主机环境,需放行 9000 端口:

1
iptables -A INPUT -p tcp --dport 9000 -j ACCEPT

📜 完整 Nginx 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_index index.php;
try_files $uri =404;
}
}

🔍 深度排查命令

1. 测试 PHP-FPM 端口连通性

1
2
apt-get install telnet
telnet 127.0.0.1 9000

如果连接失败,说明 PHP-FPM 未监听或防火墙阻止。

2. 查看 PHP-FPM 错误日志

1
tail -f /var/log/php7.4-fpm.log

常见错误:

  • WARNING: [pool www] server reached pm.max_children → 需增加 pm.max_children 值。
  • NOTICE: denied request from 172.17.0.3listen.allowed_clients 未包含 Nginx IP。

3. 验证文件权限

确保 Nginx(用户 www-data)有权限读取 PHP 文件:

1
2
3
chown -R www-data:www-data /var/www/html
find /var/www/html -type f -exec chmod 644 {} \;
find /var/www/html -type d -exec chmod 755 {} \;

🐳 Docker 专用建议

如果使用 Docker,确保:

  1. Nginx 和 PHP-FPM 在同一个网络
    1
    docker network inspect bridge | grep -A 5 Containers
  2. PHP-FPM 容器暴露 9000 端口
    1
    2
    3
    4
    5
    6
    # docker-compose.yml
    services:
    php:
    image: php:7.4-fpm
    ports:
    - "9000:9000"

最终验证

  1. 创建测试文件 /var/www/html/info.php
    1
    <?php phpinfo(); ?>
  2. 访问 http://localhost/info.php,应显示 PHP 信息页。

如果仍失败,请提供:

  • netstat -tulnp | grep 9000 输出
  • tail -n 20 /var/log/php7.4-fpm.log 日志
  • docker inspect <container_id> | grep IPAddress(如果使用 Docker)

时间: 2025-04-02T20:58:22


👤 用户

root@d80d5cddc819:/var/www/html# telnet 127.0.0.1 9000
Trying 127.0.0.1…
Connected to 127.0.0.1.
Escape character is ‘^]’.
Connection closed by foreign host.

时间: 2025-04-02T21:08:21


🤖 DeepSeek (deepseek-chat)

从你的 telnet 127.0.0.1 9000 测试结果来看,PHP-FPM 正在监听 9000 端口(能连接但立即关闭是正常行为,因为 PHP-FPM 需要 FastCGI 协议通信)。问题出在 Nginx 和 PHP-FPM 的配置交互上。以下是终极解决方案:


🔥 关键修复步骤

1. 强制检查 Nginx 的 SCRIPT_FILENAME 传递

修改 Nginx 配置,显式声明文件路径:

1
2
3
4
5
6
7
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 绝对路径必须正确
fastcgi_param DOCUMENT_ROOT $document_root; # 显式传递文档根目录
try_files $uri =404; # 防止任意文件执行
}

2. 验证 PHP-FPM 的 chroot 设置

检查 /etc/php/7.4/fpm/pool.d/www.conf

1
grep -E 'chroot|doc_root' /etc/php/7.4/fpm/pool.d/www.conf

如果存在 chrootdoc_root 设置,需与 Nginx 的 root 路径一致,或直接注释掉这些行。

3. 彻底检查文件路径映射

在容器内运行:

1
2
echo "Nginx root: $(nginx -T 2>&1 | grep 'root ')"  # 确认 Nginx 的 root 路径
ls -l $document_root/index.php # 确认 PHP 文件是否存在且可读

确保 $document_root(如 /var/www/html)是 Nginx 和 PHP-FPM 共同认可的路径

4. 启用 PHP-FPM 详细日志

编辑 /etc/php/7.4/fpm/php-fpm.conf

1
2
[global]
log_level = debug

重启 PHP-FPM 后查看日志:

1
2
killall php-fpm && php-fpm -D
tail -f /var/log/php7.4-fpm.log

📜 终极 Nginx 配置模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;

# 关键参数(必须与容器内路径完全一致)
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;

# 安全设置
try_files $uri =404;
fastcgi_read_timeout 300;
}
}

🐞 故障树分析

现象 可能原因 解决方案
能连接 9000 但下载 PHP 文件 SCRIPT_FILENAME 未传递正确 显式声明 $document_root$fastcgi_script_name
返回 404 错误 文件路径不匹配 检查 roottry_files
返回 502 Bad Gateway PHP-FPM 崩溃或权限问题 查看 PHP-FPM 日志

最终验证命令

1
2
3
4
5
6
# 1. 确认 PHP 文件可访问
curl -I http://localhost/index.php

# 2. 检查 FastCGI 通信
apt-get install cgi-fcgi
SCRIPT_NAME=/index.php SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000

如果第二步返回 PHP 代码而非文件下载,则 Nginx 配置有问题;如果返回空白,PHP-FPM 解析失败。


🐳 Docker 特有注意项

如果使用 Docker,确保:

  1. Nginx 和 PHP-FPM 共享相同的 /var/www/html
    1
    2
    volumes:
    - ./html:/var/www/html # 主机路径:容器路径
  2. 禁用 PHP-FPM 的 chroot
    1
    2
    ; /etc/php/7.4/fpm/pool.d/www.conf
    chroot = /

请执行以上步骤后提供:

  • nginx -T 输出(测试 Nginx 完整配置)
  • curl -v http://localhost/index.php 结果
  • tail -n 20 /var/log/php7.4-fpm.log 日志片段

时间: 2025-04-02T21:08:21


👤 用户

server {
listen 80;
client_max_body_size 50M;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
    try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_index index.php;
    
    # 安全设置
    try_files $uri =404;
    
    # 性能优化
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
}

# 禁止访问敏感文件
location ~ /(\.ht|vendor|composer\.json) {
    deny all;
}

}

我已经确认,index.php文件是存在于/var/www/html目录

root@d80d5cddc819:/var/www/html# grep -E ‘chroot|doc_root’ /etc/php/7.4/fpm/pool.d/www.conf
; - ‘chroot’
; absolute path. When this value is not set, chroot is not used.
; Note: you can prefix with ‘$prefix’ to chroot to the pool prefix or one
; Note: chrooting is a great security feature and should be used whenever
; possible. However, all PHP paths will be relative to the chroot
;chroot =
; Default Value: current directory or / when chroot
root@d80d5cddc819:/var/www/html# echo “Nginx root: $(nginx -T 2>&1 | grep ‘root ‘)”
Nginx root: root /var/www/html;
root /var/www/html;

root /var/www/example.com;

root@d80d5cddc819:/var/www/html# ls -l $document_root/index.ph
ls: cannot access ‘/index.ph’: No such file or directory
root@d80d5cddc819:/var/www/html# ls -l $document_root/re/index.php
ls: cannot access ‘/re/index.php’: No such file or directory
root@d80d5cddc819:/var/www/html# ls -l $document_root/index.php
ls: cannot access ‘/index.php’: No such file or directory
root@d80d5cddc819:/var/www/html#

时间: 2025-04-02T21:15:21


🤖 DeepSeek (deepseek-chat)

根据你的最新检查结果,发现了关键问题:$document_root 变量在容器内未正确解析,导致 Nginx 无法定位 PHP 文件。以下是完整解决方案:


🔧 终极修复步骤

1. 强制指定绝对路径(关键修复)

修改 Nginx 配置,将 $document_root 硬编码为 /var/www/html

1
2
3
4
5
6
7
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # 直接写绝对路径
fastcgi_index index.php;
try_files $uri =404;
}

2. 验证文件真实路径

在容器内执行:

1
2
ls -l /var/www/html/index.php  # 确认文件是否存在
stat /var/www/html/index.php # 检查权限(www-data用户需可读)

正常输出应类似:

1
-rw-r--r-- 1 www-data www-data 20 Jun 1 00:00 /var/www/html/index.php

3. 检查 PHP-FPM 环境

确认 PHP-FPM 的 env[PATH] 包含 /var/www/html

1
grep -A 5 'env\[PATH\]' /etc/php/7.4/fpm/pool.d/www.conf

若无则添加:

1
env[PATH] = /usr/local/bin:/usr/bin:/bin:/var/www/html

4. 完整测试流程

1
2
3
4
5
6
# 重启服务
killall php-fpm && php-fpm -D
nginx -s reload

# 测试通信
curl -v "http://localhost/index.php"

🐞 问题根源分析

现象 原因 解决方案
ls $document_root/index.php 报错 $document_root 未定义或为空 硬编码绝对路径 /var/www/html
文件存在但无法访问 权限问题 chown -R www-data:www-data /var/www/html
PHP-FPM 不解析 SCRIPT_FILENAME 传递失败 显式声明完整文件路径

📜 最终确认的 Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
listen 80;
client_max_body_size 50M;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # 关键修复
fastcgi_index index.php;
try_files $uri =404;

fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
}

location ~ /(\.ht|vendor|composer\.json) {
deny all;
}
}

验证方法

  1. 检查文件路径

    1
    2
    echo "Nginx root: $(nginx -T 2>&1 | grep 'root ')"
    ls -l /var/www/html/index.php
  2. 测试 PHP 解析

    1
    curl -v "http://localhost/index.php" | head -n 10

    应返回 PHP 解析后的内容,而非文件下载。

  3. 查看错误日志

    1
    tail -f /var/log/nginx/error.log /var/log/php7.4-fpm.log

如果仍不工作,请执行以下命令并提供输出:

1
2
3
4
5
# 检查 PHP-FPM 进程是否正在处理请求
strace -p $(pgrep php-fpm) -s 1024 -f

# 检查文件系统映射
mount | grep /var/www/html

时间: 2025-04-02T21:15:21


👤 用户

对了,我在宿主机已经运行了其他的mysql 以及 nginx ,我此次的镜像里同时包含了这两个服务,会不会是由于我没有定义端口的问题?

时间: 2025-04-02T21:19:49


🤖 DeepSeek (deepseek-chat)

是的!端口冲突是极有可能导致问题的原因。你在宿主机已经运行了 MySQL 和 Nginx,而 Docker 容器内也运行了相同的服务,如果端口没有正确映射,会导致服务冲突,从而出现 Nginx 无法处理 PHP 请求的问题。


🔧 解决方案:检查并修复端口冲突

1. 确认宿主机已占用的端口

在宿主机运行以下命令,查看哪些端口被占用:

1
sudo netstat -tulnp | grep -E '80|3306'  # 检查 80(Nginx)和 3306(MySQL)

如果输出类似:

1
2
tcp6   0    0 :::80      :::*    LISTEN    1234/nginx
tcp6 0 0 :::3306 :::* LISTEN 5678/mysqld

说明宿主机已经占用了 803306 端口,Docker 容器内的服务无法直接绑定这些端口。


2. 修改 Docker 容器的端口映射

方法 1:修改 docker run 命令(临时测试)

如果你直接运行容器,可以指定不同的端口映射:

1
2
3
4
docker run -d \
-p 8080:80 \ # 将宿主机的 8080 映射到容器的 80(Nginx)
-p 3307:3306 \ # 将宿主机的 3307 映射到容器的 3306(MySQL)
your-nginx-php-image

然后访问 http://localhost:8080 测试 PHP 是否正常解析。

方法 2:修改 docker-compose.yml(推荐)

如果你使用 docker-compose,调整端口映射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: "3.8"
services:
nginx:
image: nginx:alpine
ports:
- "8080:80" # 宿主机 8080 → 容器 80
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./html:/var/www/html
depends_on:
- php

php:
image: php:7.4-fpm
volumes:
- ./html:/var/www/html

mysql:
image: mysql:5.7
ports:
- "3307:3306" # 宿主机 3307 → 容器 3306
environment:
MYSQL_ROOT_PASSWORD: your_password

然后运行:

1
docker-compose up -d

访问 http://localhost:8080 测试 PHP。


3. 检查 Docker 容器内的服务是否正常运行

进入容器检查:

1
2
3
4
5
6
7
8
9
10
docker exec -it your-container-name bash

# 检查 Nginx 是否监听 80
netstat -tulnp | grep nginx

# 检查 PHP-FPM 是否监听 9000
netstat -tulnp | grep php-fpm

# 检查 MySQL 是否监听 3306
netstat -tulnp | grep mysql

如果容器内的服务没有运行,可能是启动命令有问题。


4. 最终验证

  1. 访问 http://localhost:8080/info.php(如果映射到 8080)
  2. 检查日志
    1
    2
    docker logs your-nginx-container
    docker logs your-php-container
  3. 如果仍然无法解析 PHP
    • 确保 fastcgi_pass 指向正确的 PHP-FPM 地址(如 php:9000)。
    • 确保 index.php 文件权限正确(chmod 644 /var/www/html/index.php)。

📌 总结

问题 解决方案
宿主机 80 端口被占用 修改 Docker 映射,如 8080:80
宿主机 3306 端口被占用 修改 MySQL 映射,如 3307:3306
PHP 文件仍然被下载 检查 fastcgi_passSCRIPT_FILENAME
Nginx 或 PHP-FPM 未启动 进入容器手动启动服务

请尝试修改端口映射后重新测试,如果仍有问题,请提供:

  • docker ps 输出
  • curl -v http://localhost:8080/index.php 结果
  • docker logs <container-name> 日志片段

时间: 2025-04-02T21:19:49


👤 用户

不是的,我这两个服务已经使用其他容器运行的,使用了默认端口。这样也会冲突对吧?

时间: 2025-04-02T21:21:46


🤖 DeepSeek (deepseek-chat)

是的,即使 MySQL 和 Nginx 运行在不同的 Docker 容器里,如果它们都尝试绑定宿主机的相同端口(如 80 或 3306),仍然会发生冲突,导致服务无法正常启动或访问异常。以下是详细分析和解决方案:


🔍 问题分析

1. 端口冲突的场景

  • 宿主机端口被占用(最直接的影响)
    如果宿主机已经运行了 Nginx(监听 80)或 MySQL(监听 3306),其他容器再映射相同端口时会失败(报错 Bind for 0.0.0.0:80 failed: port is already allocated)。

  • 容器间端口冲突(间接影响)
    即使宿主机端口未被占用,如果多个容器同时映射宿主机的同一个端口(如两个容器都映射 -p 80:80),后启动的容器会失败。

2. 你的当前情况

  • 宿主机已运行 Nginx(80)和 MySQL(3306)(可能是直接安装或通过其他容器运行)。
  • 新启动的容器也尝试绑定 80 和 3306,导致冲突。

🛠 解决方案

方法 1:修改新容器的端口映射(推荐)

让新容器使用不同的宿主机端口,避免冲突:

1
2
3
4
5
# 示例:将新容器的 80 映射到宿主机的 8080,3306 映射到 3307
docker run -d \
-p 8080:80 \ # 访问 http://localhost:8080
-p 3307:3306 \ # MySQL 通过 3307 连接
your-image

验证:

1
2
curl http://localhost:8080/info.php  # 测试 PHP 解析
mysql -h 127.0.0.1 -P 3307 -u root -p # 测试 MySQL

方法 2:停止宿主机或其他容器的冲突服务

如果宿主机本身运行了 Nginx/MySQL,可以停用它们:

1
2
3
4
5
# 停止宿主机 Nginx
sudo systemctl stop nginx

# 停止宿主机 MySQL
sudo systemctl stop mysql

然后重新启动你的容器(此时可正常绑定 80 和 3306)。

方法 3:使用 Docker 网络隔离

如果多个容器需要同时运行 Nginx/MySQL,但不想改端口,可以通过 Docker 自定义网络 让它们内部通信,仅暴露一个 Nginx 到宿主机

1
2
3
4
5
6
7
8
# 创建自定义网络
docker network create my_net

# 启动 MySQL 容器(不映射宿主机端口,仅内部访问)
docker run -d --network my_net --name mysql -e MYSQL_ROOT_PASSWORD=123 mysql:5.7

# 启动 PHP+Nginx 容器(仅映射 80)
docker run -d --network my_net -p 80:80 your-nginx-php-image

此时:

  • 宿主机访问 http://localhost → 进入 Nginx 容器。
  • Nginx 容器内访问 mysql:3306 → 连接到 MySQL 容器(无需映射到宿主机)。

📌 关键检查步骤

  1. 查看宿主机已用端口

    1
    sudo netstat -tulnp | grep -E '80|3306'
    • 如果输出显示 nginx/mysqld,说明宿主机已占用端口。
    • 如果显示 docker-proxy,说明其他容器已占用。
  2. 查看 Docker 容器端口映射

    1
    docker ps --format "table {{.Names}}\t{{.Ports}}"

    输出示例:

    1
    2
    3
    NAMES          PORTS
    nginx-old 0.0.0.0:80->80/tcp
    mysql-old 0.0.0.0:3306->3306/tcp
  3. 测试端口是否被占用

    1
    2
    telnet localhost 80      # 如果连通,说明端口已被占用
    telnet localhost 3306

✅ 最终方案选择

场景 解决方案 优缺点
宿主机/其他容器已占用端口 修改新容器端口(如 -p 8080:80 ✅ 简单易行,适合测试环境
需要长期运行多套服务 使用 Docker 自定义网络隔离 ✅ 更干净,适合生产环境
宿主机服务可停用 停止宿主机 Nginx/MySQL ⚠️ 影响宿主机其他服务

🚨 常见错误排查

  1. Bind for 0.0.0.0:80 failed: port is already allocated
    → 宿主机或其他容器已占用 80,改用 -p 8080:80

  2. Nginx 能访问,但 PHP 文件被下载
    → 确保 fastcgi_pass 指向正确的 PHP-FPM 地址(如 127.0.0.1:9000php:9000)。

  3. MySQL 连接失败
    → 检查容器是否映射了正确端口(如 -p 3307:3306),并确保 MySQL 容器已启动。


如果仍有问题,请提供:

  • docker ps -a 输出
  • sudo netstat -tulnp | grep -E '80|3306' 结果
  • docker logs <你的容器名> 中的错误日志

时间: 2025-04-02T21:21:46


👤 用户

那帮我修改下配置,这个镜像里已经默认内置了python-nginx-php

version: ‘3.3’

services:
web:
image: python-nginx-php-web:latest
container_name: web_server
restart: unless-stopped
ports:
- “8085:80”
volumes:
- ./html:/var/www/html
- ./config/nginx:/etc/nginx/conf.d # Nginx配置移到config目录
- ./config/php:/etc/php/7.4/fpm/conf.d # PHP配置移到config目录
depends_on:
- db
networks:
- app_net

db:
image: mysql:5.7
container_name: mysql_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: yourpassword
volumes:
- mysql-data:/var/lib/mysql # 使用命名的卷(您强调的重点)
- ./config/mysql:/etc/mysql/conf.d # MySQL配置移到config目录
networks:
- app_net

volumes:
mysql-data: # 明确定义外部卷(关键补充)

networks:
app_net:

时间: 2025-04-02T21:23:54


🤖 DeepSeek (deepseek-chat)

根据你的需求,我优化了 docker-compose.yml 配置,确保 Nginx、PHP 和 MySQL 协同工作,并避免端口冲突。以下是修正后的版本:


🚀 优化后的 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
version: '3.8'

services:
web:
image: python-nginx-php-web:latest
container_name: web_server
restart: unless-stopped
ports:
- "8085:80" # 宿主机 8085 映射到容器 80(避免与宿主机 Nginx 冲突)
volumes:
- ./html:/var/www/html
- ./config/nginx:/etc/nginx/conf.d
- ./config/php:/etc/php/7.4/fpm/conf.d
environment:
- PHP_FPM_HOST=127.0.0.1:9000 # 显式指定 PHP-FPM 地址
depends_on:
- db
networks:
- app_net

db:
image: mysql:5.7
container_name: mysql_db
restart: unless-stopped
ports:
- "3307:3306" # 宿主机 3307 映射到容器 3306(避免与宿主机 MySQL 冲突)
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: yourpassword
volumes:
- mysql-data:/var/lib/mysql
- ./config/mysql:/etc/mysql/conf.d
networks:
- app_net

volumes:
mysql-data:

networks:
app_net:
driver: bridge

🔧 关键优化点

  1. 端口冲突解决

    • Nginx 使用 8085:80(避免与宿主机或其他容器的 80 端口冲突)。
    • MySQL 使用 3307:3306(避免与宿主机的 3306 冲突)。
  2. PHP-FPM 连接优化

    • 通过环境变量 PHP_FPM_HOST=127.0.0.1:9000 确保 Nginx 能正确找到 PHP-FPM(如果镜像内 PHP-FPM 和 Nginx 在同一容器)。
  3. 网络隔离

    • 所有服务在 app_net 网络内通信,确保容器间可通过服务名(如 db)直接访问。
  4. 数据持久化

    • MySQL 数据保存在命名卷 mysql-data,即使容器重启也不会丢失。

📌 需要检查的配置

1. Nginx 配置(./config/nginx/default.conf

确保 fastcgi_pass 指向正确的 PHP-FPM 地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;

location ~ \.php$ {
fastcgi_pass ${PHP_FPM_HOST}; # 使用环境变量
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
}
}

2. PHP-FPM 配置(./config/php/zzz-custom.conf

检查是否监听 9000 端口:

1
2
3
4
[www]
listen = 9000
listen.owner = www-data
listen.group = www-data

🚀 启动步骤

  1. 创建目录结构:

    1
    mkdir -p {html,config/{nginx,php,mysql}}
  2. 将你的 Nginx、PHP、MySQL 配置文件放入对应目录:

    • ./config/nginx/default.conf(Nginx 配置)
    • ./config/php/zzz-custom.conf(PHP 配置)
    • ./config/mysql/custom.cnf(MySQL 配置,可选)
  3. 启动服务:

    1
    docker-compose up -d
  4. 测试:

    • 访问 http://localhost:8085/info.php 应显示 PHP 信息。
    • 连接 MySQL:
      1
      mysql -h 127.0.0.1 -P 3307 -u wordpress -p

🐞 常见问题排查

  1. Nginx 返回 502 Bad Gateway

    • 检查 PHP-FPM 是否运行:
      1
      docker exec web_server ps aux | grep php-fpm
    • 检查 fastcgi_pass 是否指向正确的地址(如 127.0.0.1:9000)。
  2. MySQL 无法连接

    • 确认端口映射正确(3307:3306)。
    • 检查日志:
      1
      docker logs mysql_db
  3. PHP 文件被直接下载

    • 确保 location ~ \.php$ 配置正确,且 SCRIPT_FILENAME 包含完整路径。

✅ 最终验证

1
2
3
4
5
6
7
8
# 检查容器状态
docker ps

# 查看 Nginx 日志
docker logs web_server

# 测试 PHP 解析
curl -v http://localhost:8085/info.php

如果仍有问题,请提供:

  • docker-compose logs web 输出
  • cat ./config/nginx/default.conf 内容
  • curl -v http://localhost:8085/index.php 的完整响应

时间: 2025-04-02T21:23:54


👤 用户

PHP_FPM_HOST=127.0.0.1:9000 这个需要修改吗?可能其他容器也内置使用了PHP_FPM

时间: 2025-04-02T21:28:01


🤖 DeepSeek (deepseek-chat)

是的,PHP_FPM_HOST=127.0.0.1:9000 是否需要修改取决于 PHP-FPM 的实际运行位置。以下是详细分析和解决方案:


🔍 关键问题分析

  1. 如果你的 python-nginx-php-web 镜像内同时运行了 Nginx 和 PHP-FPM

    • PHP-FPM 默认监听 127.0.0.1:9000(容器内部),此时 PHP_FPM_HOST=127.0.0.1:9000 无需修改
    • 验证方法:
      1
      docker exec web_server netstat -tulnp | grep 9000
      如果输出显示 php-fpm 监听 9000 端口,则配置正确。
  2. 如果 PHP-FPM 运行在另一个容器(如独立的 php-fpm 服务)

    • 需要将 PHP_FPM_HOST 改为目标容器的服务名(如 php:9000)。
    • 此时需调整 docker-compose.yml,添加独立的 PHP-FPM 服务。

🛠 解决方案

情况 1:PHP-FPM 在 web 容器内部(当前配置)

保持现有配置,但需确保:

  • Nginx 和 PHP-FPM 在同一个容器内。
  • PHP-FPM 已启动并监听 9000 端口。

验证步骤

1
2
3
4
# 进入容器检查 PHP-FPM 进程
docker exec -it web_server bash
ps aux | grep php-fpm
netstat -tulnp | grep 9000

情况 2:PHP-FPM 在独立容器

修改 docker-compose.yml,添加 PHP-FPM 服务并调整连接方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
php:
image: php:7.4-fpm # 或其他版本
volumes:
- ./html:/var/www/html # 共享代码目录
networks:
- app_net

web:
environment:
- PHP_FPM_HOST=php:9000 # 改为 PHP-FPM 服务名
depends_on:
- php
- db

📌 配置检查清单

  1. 确认 PHP-FPM 监听地址

    • web 容器内运行:
      1
      cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
      输出应为 listen = 9000listen = 127.0.0.1:9000
  2. 检查 Nginx 的 fastcgi_pass
    确保 ./config/nginx/default.conf 中使用了环境变量:

    1
    fastcgi_pass ${PHP_FPM_HOST};
  3. 测试 PHP 解析

    1
    curl http://localhost:8085/info.php
    • 如果返回 PHP 代码而非文件下载,则配置正确。
    • 如果返回 502 错误,检查 PHP-FPM 日志:
      1
      docker logs web_server | grep php-fpm

🚨 常见问题处理

问题 1:Connection refused 错误

  • 原因:PHP-FPM 未运行或监听地址错误。
  • 解决
    1
    2
    # 进入容器手动启动 PHP-FPM
    docker exec -it web_server php-fpm -D

问题 2:Primary script unknown 错误

  • 原因SCRIPT_FILENAME 路径不正确。
  • 解决
    确保 Nginx 配置中硬编码了正确的根路径:
    1
    fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;

✅ 最终建议

  1. 如果镜像内置 PHP-FPM

    • 保持 PHP_FPM_HOST=127.0.0.1:9000
    • 进入容器检查 PHP-FPM 是否运行:
      1
      docker exec web_server ps aux | grep php-fpm
  2. 如果需要独立 PHP-FPM 容器

    • 按上述方案添加 php 服务,并修改 PHP_FPM_HOST=php:9000
  3. 强制验证
    web 容器内直接测试 FastCGI 连接:

    1
    SCRIPT_NAME=/info.php SCRIPT_FILENAME=/var/www/html/info.php cgi-fcgi -bind -connect 127.0.0.1:9000

    如果返回 PHP 代码,则通信正常。


请根据你的实际架构选择方案,并提供以下信息以便进一步排查:

  • docker exec web_server ps aux 输出(检查进程)
  • docker-compose logs web 中的错误日志
  • curl -v http://localhost:8085/info.php 的完整响应

时间: 2025-04-02T21:28:01


👤 用户

root@9b4eb9cf9368:/var/www/html# grep -A 5 ‘env[PATH]‘ /etc/php/7.4/fpm/pool.d/www.conf
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

; Additional php.ini defines, specific to this pool of workers. These settings
root@9b4eb9cf9368:/var/www/html#

时间: 2025-04-02T21:43:09


🤖 DeepSeek (deepseek-chat)

从你的检查结果来看,env[PATH] 在 PHP-FPM 配置中是被注释掉的,这意味着 PHP-FPM 没有显式设置环境变量 PATH,但这通常不会直接影响 PHP 文件的解析。当前的核心问题仍然是 Nginx 和 PHP-FPM 之间的通信


🔧 关键修复步骤

1. 强制指定 SCRIPT_FILENAME(绝对路径)

修改 Nginx 配置(./config/nginx/default.conf),硬编码 PHP 文件的绝对路径:

1
2
3
4
5
6
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 确保与 PHP-FPM 监听地址一致
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # 关键修复!
try_files $uri =404;
}

2. 检查 PHP-FPM 的监听地址

在容器内运行:

1
cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
  • 如果输出 listen = 9000listen = 127.0.0.1:9000,则 fastcgi_pass 127.0.0.1:9000 正确。
  • 如果输出 listen = /var/run/php/php7.4-fpm.sock,需改用:
    1
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

3. 验证 PHP-FPM 是否真正运行

1
ps aux | grep php-fpm

如果没有输出,手动启动:

1
php-fpm -D

4. 检查文件权限

确保 /var/www/html 可被 www-data 用户读取:

1
2
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html

📌 验证方法

  1. 测试 FastCGI 通信
    在容器内执行:

    1
    2
    apt-get install cgi-fcgi
    SCRIPT_NAME=/info.php SCRIPT_FILENAME=/var/www/html/info.php cgi-fcgi -bind -connect 127.0.0.1:9000
    • 如果返回 PHP 代码,说明 PHP-FPM 工作正常。
    • 如果返回 502 Bad Gateway,检查 PHP-FPM 日志:
      1
      tail -f /var/log/php7.4-fpm.log
  2. 检查 Nginx 错误日志

    1
    tail -f /var/log/nginx/error.log

    常见错误:

    • Primary script unknownSCRIPT_FILENAME 路径错误。
    • Connection refused → PHP-FPM 未运行或监听地址错误。

🚨 常见问题解决

问题现象 原因 解决方案
PHP 文件被下载 fastcgi_pass 配置错误 检查 PHP-FPM 监听地址
502 Bad Gateway PHP-FPM 未运行 执行 php-fpm -D
Primary script unknown SCRIPT_FILENAME 路径错误 硬编码 /var/www/html$fastcgi_script_name

✅ 最终确认

  1. 确保 docker-compose.ymlweb 服务的端口映射正确:
    1
    2
    ports:
    - "8085:80" # 宿主机 8085 → 容器 80
  2. 访问 http://localhost:8085/info.php,应显示 PHP 信息页。

如果仍有问题,请提供:

  • docker exec web_server cat /etc/nginx/conf.d/default.conf
  • docker logs web_server 的输出
  • curl -v http://localhost:8085/info.php 的完整响应

时间: 2025-04-02T21:43:09


👤 用户

root@9b4eb9cf9368:/var/www/html# echo “Nginx root: $(nginx -T 2>&1 | grep ‘root ‘)”
Nginx root: root /var/www/html;
root /var/www/html;

root /var/www/example.com;

root@9b4eb9cf9368:/var/www/html# ls -l $document_root/index.php
ls: cannot access ‘/index.php’: No such file or directory
root@9b4eb9cf9368:/var/www/html#

上面好像是找不到index.php,但是我web访问index.php是把这个文件下载了

时间: 2025-04-02T21:48:52


🤖 DeepSeek (deepseek-chat)

从你的检查结果来看,问题核心是:Nginx 能访问到 /var/www/html/index.php 文件(否则会返回 404),但却无法正确交给 PHP-FPM 解析,导致文件被直接下载。以下是终极解决方案:


🔧 问题根源与修复步骤

1. 确认文件真实路径

在容器内执行:

1
ls -l /var/www/html/index.php  # 确认文件是否存在且路径正确
  • 如果文件存在,继续下一步。
  • 如果不存在,检查你的 docker-compose.yml./html 卷挂载是否正确。

2. 强制修正 Nginx 的 SCRIPT_FILENAME

编辑 Nginx 配置(./config/nginx/default.conf),硬编码绝对路径

1
2
3
4
5
6
7
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 必须与 PHP-FPM 监听地址一致
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # 关键修复!
fastcgi_param DOCUMENT_ROOT /var/www/html; # 显式声明根目录
try_files $uri =404;
}

3. 验证 PHP-FPM 配置

在容器内检查:

1
cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
  • 如果输出 listen = 9000listen = 127.0.0.1:9000,保持 fastcgi_pass 127.0.0.1:9000
  • 如果输出 listen = /var/run/php/php7.4-fpm.sock,需改用:
    1
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

4. 重启服务

1
docker-compose restart web

📌 关键检查点

  1. 文件权限
    确保 www-data 用户可读文件:

    1
    2
    chown -R www-data:www-data /var/www/html
    chmod -R 755 /var/www/html
  2. 测试 FastCGI 通信
    在容器内手动测试 PHP-FPM 是否能解析文件:

    1
    2
    apt-get install cgi-fcgi
    SCRIPT_NAME=/index.php SCRIPT_FILENAME=/var/www/html/index.php cgi-fcgi -bind -connect 127.0.0.1:9000
    • 如果返回 PHP 代码,说明 PHP-FPM 正常。
    • 如果失败,检查 PHP-FPM 日志:
      1
      tail -f /var/log/php7.4-fpm.log
  3. Nginx 错误日志

    1
    tail -f /var/log/nginx/error.log

    常见错误:

    • Primary script unknownSCRIPT_FILENAME 路径错误。
    • Connection refused → PHP-FPM 未运行。

🚨 常见问题解决方案

现象 原因 修复方法
文件被下载 fastcgi_pass 配置错误 检查 PHP-FPM 监听地址
502 Bad Gateway PHP-FPM 未运行 执行 php-fpm -D
404 Not Found 文件路径错误 检查 root 和文件位置

最终验证

访问 http://localhost:8085/index.php,应该显示:

  • PHP 解析后的页面(成功)
  • 或直接下载文件(失败,需检查上述步骤)

如果仍然失败,请提供:

  • docker exec web_server cat /etc/nginx/conf.d/default.conf
  • docker logs web_server 的输出
  • curl -v http://localhost:8085/index.php 的完整响应

时间: 2025-04-02T21:48:52


👤 用户

server {
listen 80;
client_max_body_size 50M;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; 
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT /var/www/html; 
fastcgi_index index.php;
try_files $uri =404;
    
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
}

location ~ /(\.ht|vendor|composer\.json) {
deny all;
}

}

时间: 2025-04-02T21:57:35


🤖 DeepSeek (deepseek-chat)

根据你提供的完整 Nginx 配置和之前的排查结果,你的配置在语法上是正确的,但 PHP 文件仍然被下载,说明问题出在 Nginx 和 PHP-FPM 的实际通信环节。以下是终极解决方案:


🔧 关键修复步骤

1. 确认 PHP-FPM 真实运行状态

在容器内执行:

1
2
3
4
5
# 检查 PHP-FPM 进程是否存在
ps aux | grep php-fpm

# 检查 9000 端口监听情况
netstat -tulnp | grep 9000
  • 如果没有运行,手动启动:
    1
    php-fpm -D
  • 如果端口未监听,检查 /etc/php/7.4/fpm/pool.d/www.conf 中的 listen 值。

2. 强制测试 FastCGI 通信

在容器内直接测试 PHP-FPM 是否能解析文件:

1
2
apt-get update && apt-get install -y cgi-fcgi
SCRIPT_NAME=/index.php SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
  • 成功:返回 PHP 解析后的内容 → Nginx 配置有问题。
  • 失败:返回空或错误 → PHP-FPM 配置问题。

3. 检查 PHP-FPM 的 listen 配置

1
cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
  • 如果是 listen = /var/run/php/php7.4-fpm.sock,需修改 Nginx 配置:
    1
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

4. 验证文件所有权

1
2
3
ls -l /var/www/html/index.php
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html

5. 检查关键日志

1
2
3
4
5
# Nginx 错误日志
tail -f /var/log/nginx/error.log

# PHP-FPM 日志
tail -f /var/log/php7.4-fpm.log

📜 修正后的 Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
server {
listen 80;
client_max_body_size 50M;
server_name localhost;
root /var/www/html;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
# 关键点:确认使用 TCP 或 Unix Socket
fastcgi_pass 127.0.0.1:9000; # 或 unix:/var/run/php/php7.4-fpm.sock;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_index index.php;

# 安全设置
try_files $uri =404;

# 性能优化
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
}

location ~ /(\.ht|vendor|composer\.json) {
deny all;
}
}

🚨 终极排查流程图

1
2
3
4
5
6
7
8
9
10
graph TD
A[PHP文件被下载] --> B{检查PHP-FPM是否运行?}
B -->|是| C[测试FastCGI通信]
B -->|否| D[启动php-fpm -D]
C -->|成功| E[检查Nginx配置]
C -->|失败| F[检查PHP-FPM日志]
E --> G[确认fastcgi_pass地址]
G -->|TCP| H[验证127.0.0.1:9000]
G -->|Unix| I[验证socket路径]
F --> J[检查listen和权限]

验证命令

1
2
3
4
5
6
7
8
9
# 1. 测试PHP解析(容器内)
curl -v localhost/index.php

# 2. 检查端口监听(容器内)
ss -tulnp | grep -E '80|9000'

# 3. 查看服务状态(容器内)
service nginx status
service php7.4-fpm status

如果问题仍未解决,请提供以下信息:

  1. docker exec web_server cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
  2. docker exec web_server tail -n 20 /var/log/php7.4-fpm.log
  3. curl -v http://localhost:8085/index.php 的完整输出(含HTTP头)

时间: 2025-04-02T21:57:35


👤 用户

root@iZuf6fefuxxxptmtvjnf0rZ:~/docker/ubuntu# docker exec -it web_server /bin/bash
root@9b4eb9cf9368:/var/www/html# ps aux | grep php-fpm
root 15 0.0 0.3 55820 7216 ? Ss 21:59 0:00 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
www-data 16 0.0 0.3 55820 6608 ? S 21:59 0:00 php-fpm: pool www
www-data 17 0.0 0.3 55820 6608 ? S 21:59 0:00 php-fpm: pool www
root 27 0.0 0.0 8164 712 pts/0 S+ 22:00 0:00 grep –color=auto php-fpm
root@9b4eb9cf9368:/var/www/html# netstat -tulnp | grep 9000
bash: netstat: command not found
root@9b4eb9cf9368:/var/www/html# apt-get update && apt-get install -y cgi-fcgi
Get:1 http://mirrors.aliyun.com/ubuntu focal InRelease [265 kB]
Get:2 http://mirrors.aliyun.com/ubuntu focal-updates InRelease [128 kB]
Get:3 http://mirrors.aliyun.com/ubuntu focal-backports InRelease [128 kB]
Get:4 http://mirrors.aliyun.com/ubuntu focal-security InRelease [128 kB]
Get:5 http://mirrors.aliyun.com/ubuntu focal/multiverse amd64 Packages [177 kB]
Get:6 http://mirrors.aliyun.com/ubuntu focal/restricted amd64 Packages [33.4 kB]
Get:7 http://mirrors.aliyun.com/ubuntu focal/main amd64 Packages [1275 kB]
Get:8 http://mirrors.aliyun.com/ubuntu focal/universe amd64 Packages [11.3 MB]
Get:9 http://mirrors.aliyun.com/ubuntu focal-updates/universe amd64 Packages [1597 kB]
Get:10 http://mirrors.aliyun.com/ubuntu focal-updates/restricted amd64 Packages [4738 kB]
Get:11 http://mirrors.aliyun.com/ubuntu focal-updates/multiverse amd64 Packages [36.8 kB]
Get:12 http://mirrors.aliyun.com/ubuntu focal-updates/main amd64 Packages [4804 kB]
Get:13 http://mirrors.aliyun.com/ubuntu focal-backports/universe amd64 Packages [28.6 kB]
Get:14 http://mirrors.aliyun.com/ubuntu focal-backports/main amd64 Packages [55.2 kB]
Get:15 http://mirrors.aliyun.com/ubuntu focal-security/restricted amd64 Packages [4540 kB]
Get:16 http://mirrors.aliyun.com/ubuntu focal-security/universe amd64 Packages [1304 kB]
Get:17 http://mirrors.aliyun.com/ubuntu focal-security/main amd64 Packages [4317 kB]
Get:18 http://mirrors.aliyun.com/ubuntu focal-security/multiverse amd64 Packages [33.2 kB]
Fetched 34.9 MB in 3s (10.6 MB/s)
Reading package lists… Done
Reading package lists… Done
Building dependency tree
Reading state information… Done
E: Unable to locate package cgi-fcgi
root@9b4eb9cf9368:/var/www/html# SCRIPT_NAME=/index.php SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
bash: cgi-fcgi: command not found
root@9b4eb9cf9368:/var/www/html# cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
; - ‘listen’ (unixsocket)
; ‘ip.add.re.ss:port’ - to listen on a TCP socket to a specific IPv4 address on
; ‘[ip:6:addr:ess]:port’ - to listen on a TCP socket to a specific IPv6 address on
; ‘port’ - to listen on a TCP socket to all addresses
; ‘/path/to/unix/socket’ - to listen on a unix socket.
listen = 127.0.0.1:9000
; Set listen(2) backlog.
;listen.backlog = 511
listen.owner = www-data
listen.group = www-data
;listen.mode = 0660
; When set, listen.owner and listen.group are ignored
;listen.acl_users =
;listen.acl_groups =
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
;listen.allowed_clients = 127.0.0.1
; listen queue - the number of request in the queue of pending
; connections (see backlog in listen(2));
; max listen queue - the maximum number of requests in the queue
; listen queue len - the size of the socket queue of pending connections;
; listen queue: 0
; max listen queue: 1
; listen queue len: 42
root@9b4eb9cf9368:/var/www/html# nano /etc/php/7.4/fpm/pool.d/www.conf
bash: nano: command not found
root@9b4eb9cf9368:/var/www/html# aptget install nano
bash: aptget: command not found
root@9b4eb9cf9368:/var/www/html# apt-get install nano
Reading package lists… Done
Building dependency tree
Reading state information… Done
Suggested packages:
hunspell
The following NEW packages will be installed:
nano
0 upgraded, 1 newly installed, 0 to remove and 3 not upgraded.
Need to get 269 kB of archives.
After this operation, 868 kB of additional disk space will be used.
Get:1 http://mirrors.aliyun.com/ubuntu focal-updates/main amd64 nano amd64 4.8-1ubuntu1.1 [269 kB]
Fetched 269 kB in 0s (4999 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package nano.
(Reading database … 21325 files and directories currently installed.)
Preparing to unpack …/nano_4.8-1ubuntu1.1_amd64.deb …
Unpacking nano (4.8-1ubuntu1.1) …
Setting up nano (4.8-1ubuntu1.1) …
update-alternatives: using /bin/nano to provide /usr/bin/editor (editor) in auto mode
update-alternatives: warning: skip creation of /usr/share/man/man1/editor.1.gz because associated file /usr/share/man/man1/nano.1.gz (of link group editor) doesn’t exist
update-alternatives: using /bin/nano to provide /usr/bin/pico (pico) in auto mode
update-alternatives: warning: skip creation of /usr/share/man/man1/pico.1.gz because associated file /usr/share/man/man1/nano.1.gz (of link group pico) doesn’t exist
root@9b4eb9cf9368:/var/www/html# nano /etc/php/7.4/fpm/pool.d/www.conf
root@9b4eb9cf9368:/var/www/html# cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
; - ‘listen’ (unixsocket)
; ‘ip.add.re.ss:port’ - to listen on a TCP socket to a specific IPv4 address on
; ‘[ip:6:addr:ess]:port’ - to listen on a TCP socket to a specific IPv6 address on
; ‘port’ - to listen on a TCP socket to all addresses
; ‘/path/to/unix/socket’ - to listen on a unix socket.
listen = 127.0.0.1:9000
; Set listen(2) backlog.
;listen.backlog = 511
listen.owner = www-data
listen.group = www-data
;listen.mode = 0660
; When set, listen.owner and listen.group are ignored
;listen.acl_users =
;listen.acl_groups =
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
listen.allowed_clients = 127.0.0.1
; listen queue - the number of request in the queue of pending
; connections (see backlog in listen(2));
; max listen queue - the maximum number of requests in the queue
; listen queue len - the size of the socket queue of pending connections;
; listen queue: 0
; max listen queue: 1
; listen queue len: 42
root@9b4eb9cf9368:/var/www/html# ls -l /var/www/html/index.php
-rw-r–r– 1 www-data www-data 19 Apr 2 21:13 /var/www/html/index.php
root@9b4eb9cf9368:/var/www/html# chown -R www-data:www-data /var/www/html
root@9b4eb9cf9368:/var/www/html# chmod -R 755 /var/www/html
root@9b4eb9cf9368:/var/www/html# tail -f /var/log/nginx/error.log
2025/04/02 21:36:56 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:38:36 [error] 18#18: *4 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:47:11 [error] 18#18: *6 directory index of “/var/www/html/“ is forbidden, client: 114.225.2.2, server: _, request: “GET / HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:54:37 [error] 18#18: *1 directory index of “/var/www/html/“ is forbidden, client: 114.225.2.2, server: _, request: “GET / HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:54:50 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:54:51 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:59:37 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 22:03:36 [error] 18#18: *3 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
^C
root@9b4eb9cf9368:/var/www/html# tail -f /var/log/php7.4-fpm.log
[02-Apr-2025 13:36:41] NOTICE: fpm is running, pid 15
[02-Apr-2025 13:36:41] NOTICE: ready to handle connections
[02-Apr-2025 13:36:41] NOTICE: systemd monitor interval set to 10000ms
[02-Apr-2025 13:54:31] NOTICE: fpm is running, pid 15
[02-Apr-2025 13:54:31] NOTICE: ready to handle connections
[02-Apr-2025 13:54:31] NOTICE: systemd monitor interval set to 10000ms
[02-Apr-2025 13:59:32] NOTICE: fpm is running, pid 15
[02-Apr-2025 13:59:32] NOTICE: ready to handle connections
[02-Apr-2025 13:59:32] NOTICE: systemd monitor interval set to 10000ms
^C
root@9b4eb9cf9368:/var/www/html#

时间: 2025-04-02T22:05:39


🤖 DeepSeek (deepseek-chat)

根据你的完整排查结果,所有配置看起来都是正确的(PHP-FPM 在运行、Nginx 配置正确、文件权限正常),但 PHP 文件仍然被下载。这通常意味着 Nginx 和 PHP-FPM 之间的 FastCGI 通信未真正建立。以下是终极解决方案:


🔧 终极修复步骤

1. 验证 PHP-FPM 是否能处理请求

在容器内安装 telnet 并测试 9000 端口:

1
2
apt-get install -y telnet
telnet 127.0.0.1 9000
  • 如果显示 Connected to 127.0.0.1 → 端口通信正常。
  • 如果失败 → PHP-FPM 未监听 9000 端口。

2. 强制检查 SCRIPT_FILENAME 路径

在 Nginx 配置中 临时硬编码测试路径

1
2
3
4
5
6
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html/index.php; # 直接指定文件
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 注释原配置
}

重启 Nginx 后访问 http://localhost:8085/index.php

  • 如果成功 → 原配置的 $document_root$fastcgi_script_name 变量未正确解析。
  • 如果仍然下载 → PHP-FPM 未处理请求。

3. 检查 PHP-FPM 的 security.limit_extensions

编辑 /etc/php/7.4/fpm/pool.d/www.conf

1
2
; 确保允许解析 .php 文件
security.limit_extensions = .php .php3 .php4 .php5 .php7

重启 PHP-FPM:

1
killall php-fpm && php-fpm -D

4. 完整测试命令

1
2
3
4
5
6
# 测试 FastCGI 通信(容器内)
apt-get install -y libfcgi-bin
SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000

# 检查 Nginx 实际传递的路径
tail -f /var/log/nginx/error.log | grep "FastCGI"

🚨 如果仍不工作

可能原因

  1. Docker 网络问题
    Nginx 和 PHP-FPM 虽然在同一个容器,但可能因 Docker 网络隔离导致 127.0.0.1 不可达。
    解决方案

    • 改用 Unix Socket:
      1
      fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    • 或在 www.conf 中设置 listen = 0.0.0.0:9000
  2. PHP-FPM 未加载配置
    检查

    1
    php-fpm -t  # 测试配置

    修复

    • 确保 /etc/php/7.4/fpm/php-fpm.conf 包含:
      1
      include=/etc/php/7.4/fpm/pool.d/*.conf

最终确认

  1. 强制测试
    在容器内直接请求 PHP 文件:

    1
    curl -v "http://127.0.0.1/index.php"
    • 如果返回 PHP 代码 → 问题出在 Docker 端口映射或宿主机。
    • 如果下载文件 → 容器内 Nginx 和 PHP-FPM 通信失败。
  2. 简化排查
    创建一个全新的测试文件 /var/www/html/test.php

    1
    2
    3
    4
    <?php
    header('Content-Type: text/plain');
    echo "PHP is working!";
    ?>

    访问 http://localhost:8085/test.php,观察输出。


📜 修正后的 Nginx 配置(终极版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 80;
root /var/www/html;
index index.php;

location ~ \.php$ {
# 方法1:优先尝试 Unix Socket
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

# 方法2:如果必须用 TCP,确保 PHP-FPM 监听 0.0.0.0
# fastcgi_pass 127.0.0.1:9000;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
try_files $uri =404;
}
}

请执行以上步骤并反馈:

  1. telnet 127.0.0.1 9000 的结果
  2. 硬编码 SCRIPT_FILENAME 后的测试结果
  3. php-fpm -t 的输出

时间: 2025-04-02T22:05:39


👤 用户

0 upgraded, 1 newly installed, 0 to remove and 3 not upgraded. Need to
get 269 kB of archives.
After this operation, 868 kB of additional disk space will be used.
Get:1 http://mirrors.aliyun.com/ubuntu focal-updates/main amd64 nano amd64 4.8-1ubuntu1.1 [269 kB]
Fetched 269 kB in 0s (4999 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package nano.
(Reading database … 21325 files and directories currently installed.)
Preparing to unpack …/nano_4.8-1ubuntu1.1_amd64.deb …
Unpacking nano (4.8-1ubuntu1.1) …
Setting up nano (4.8-1ubuntu1.1) …
update-alternatives: using /bin/nano to provide /usr/bin/editor (editor) in auto mode
update-alternatives: warning: skip creation of /usr/share/man/man1/editor.1.gz because associated file /usr/share/man/man1/nano.1.gz (of link group editor) doesn’t exist
update-alternatives: using /bin/nano to provide /usr/bin/pico (pico) in auto mode
update-alternatives: warning: skip creation of /usr/share/man/man1/pico.1.gz because associated file /usr/share/man/man1/nano.1.gz (of link group pico) doesn’t exist
root@9b4eb9cf9368:/var/www/html# nano /etc/php/7.4/fpm/pool.d/www.conf
root@9b4eb9cf9368:/var/www/html# cat /etc/php/7.4/fpm/pool.d/www.conf | grep listen
; - ‘listen’ (unixsocket)
; ‘ip.add.re.ss:port’ - to listen on a TCP socket to a specific IPv4 address on
; ‘[ip:6:addr:ess]:port’ - to listen on a TCP socket to a specific IPv6 address on
; ‘port’ - to listen on a TCP socket to all addresses
; ‘/path/to/unix/socket’ - to listen on a unix socket.
listen = 127.0.0.1:9000
; Set listen(2) backlog.
;listen.backlog = 511
listen.owner = www-data
listen.group = www-data
;listen.mode = 0660
; When set, listen.owner and listen.group are ignored
;listen.acl_users =
;listen.acl_groups =
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
listen.allowed_clients = 127.0.0.1
; listen queue - the number of request in the queue of pending
; connections (see backlog in listen(2));
; max listen queue - the maximum number of requests in the queue
; listen queue len - the size of the socket queue of pending connections;
; listen queue: 0
; max listen queue: 1
; listen queue len: 42
root@9b4eb9cf9368:/var/www/html# ls -l /var/www/html/index.php
-rw-r–r– 1 www-data www-data 19 Apr 2 21:13 /var/www/html/index.php
root@9b4eb9cf9368:/var/www/html# chown -R www-data:www-data /var/www/html
root@9b4eb9cf9368:/var/www/html# chmod -R 755 /var/www/html
root@9b4eb9cf9368:/var/www/html# tail -f /var/log/nginx/error.log
2025/04/02 21:36:56 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:38:36 [error] 18#18: *4 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:47:11 [error] 18#18: *6 directory index of “/var/www/html/“ is forbidden, client: 114.225.2.2, server: _, request: “GET / HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:54:37 [error] 18#18: *1 directory index of “/var/www/html/“ is forbidden, client: 114.225.2.2, server: _, request: “GET / HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:54:50 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:54:51 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 21:59:37 [error] 18#18: *1 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
2025/04/02 22:03:36 [error] 18#18: *3 directory index of “/var/www/html/re/“ is forbidden, client: 114.225.2.2, server: _, request: “GET /re/ HTTP/1.1”, host: “106.15.4.153:8085”
^C
root@9b4eb9cf9368:/var/www/html# tail -f /var/log/php7.4-fpm.log
[02-Apr-2025 13:36:41] NOTICE: fpm is running, pid 15
[02-Apr-2025 13:36:41] NOTICE: ready to handle connections
[02-Apr-2025 13:36:41] NOTICE: systemd monitor interval set to 10000ms
[02-Apr-2025 13:54:31] NOTICE: fpm is running, pid 15
[02-Apr-2025 13:54:31] NOTICE: ready to handle connections
[02-Apr-2025 13:54:31] NOTICE: systemd monitor interval set to 10000ms
[02-Apr-2025 13:59:32] NOTICE: fpm is running, pid 15
[02-Apr-2025 13:59:32] NOTICE: ready to handle connections
[02-Apr-2025 13:59:32] NOTICE: systemd monitor interval set to 10000ms
^C
root@9b4eb9cf9368:/var/www/html#curl -v “http://127.0.0.1/index.php

时间: 2025-04-02T22:08:55


🤖 DeepSeek (deepseek-chat)

根据你的最新测试结果,curl -v "http://127.0.0.1/index.php" 命令没有返回任何输出,这表明请求没有成功执行或 Nginx 没有正确处理请求。结合之前的排查,以下是终极解决方案:


🔧 终极修复步骤

1. 确认 Nginx 监听 80 端口

在容器内运行:

1
ss -tulnp | grep 80
  • 如果无输出,说明 Nginx 未启动或配置错误。
  • 如果显示 0.0.0.0:80,继续下一步。

2. 强制测试 PHP-FPM 处理能力

在容器内直接发送 FastCGI 请求(无需安装额外工具):

1
2
3
4
SCRIPT_NAME=/index.php \
SCRIPT_FILENAME=/var/www/html/index.php \
REQUEST_METHOD=GET \
php-cgi -b 127.0.0.1:9000
  • 成功:返回 PHP 解析后的内容 → Nginx 配置问题。
  • 失败:PHP-FPM 配置问题。

3. 临时绕过 Nginx 测试

在容器内用 PHP 内置服务器测试:

1
php -S 0.0.0.0:8080 -t /var/www/html

另开终端访问:

1
curl -v "http://127.0.0.1:8080/index.php"
  • 如果返回 PHP 代码 → 确认 PHP 环境正常。
  • 如果仍下载 → PHP 安装或文件权限问题。

4. 检查 PHP-FPM 子进程权限

编辑 /etc/php/7.4/fpm/pool.d/www.conf

1
2
3
4
5
6
; 确保用户和组与文件权限匹配
user = www-data
group = www-data

; 检查是否限制了解析扩展
security.limit_extensions = .php

重启 PHP-FPM:

1
killall php-fpm && php-fpm -D

5. 终极 Nginx 调试配置

修改 /etc/nginx/conf.d/default.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
root /var/www/html;
index index.php;

location ~ \.php$ {
# 方法1:强制使用 Unix Socket(推荐)
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

# 方法2:如果必须用 TCP,确保 PHP-FPM 监听所有地址
# fastcgi_pass 127.0.0.1:9000;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

# 调试日志
error_log /var/log/nginx/fastcgi_error.log debug;
access_log /var/log/nginx/fastcgi_access.log;
}
}

重启 Nginx:

1
nginx -s reload

📌 关键检查点

问题 检查命令 解决方案
Nginx 未运行 ps aux | grep nginx 启动 Nginx
PHP-FPM 未处理请求 php-cgi -b 127.0.0.1:9000 检查 www.conf
文件权限问题 ls -l /var/www/html chown -R www-data:www-data /var/www/html
FastCGI 通信失败 tail -f /var/log/nginx/fastcgi_error.log 改用 Unix Socket

最终验证

  1. 测试 FastCGI 通信

    1
    SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET php-cgi -b 127.0.0.1:9000
  2. 测试 Nginx 请求

    1
    curl -v "http://127.0.0.1/index.php"
  3. 检查日志

    1
    tail -f /var/log/nginx/fastcgi_error.log

如果问题仍未解决,请提供:

  1. ss -tulnp 的输出(容器内)
  2. php-cgi -b 127.0.0.1:9000 的完整结果
  3. /var/log/nginx/fastcgi_error.log 的内容

时间: 2025-04-02T22:08:55


👤 用户

root@9b4eb9cf9368:/var/www/html# nano
root@9b4eb9cf9368:/var/www/html# ss -tulnp | grep 80
tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:((“nginx”,pid=1,fd=6))
tcp LISTEN 0 128 [::]:80 [::]:* users:((“nginx”,pid=1,fd=7))
root@9b4eb9cf9368:/var/www/html# SCRIPT_NAME=/index.php \

SCRIPT_FILENAME=/var/www/html/index.php
REQUEST_METHOD=GET
php-cgi -b 127.0.0.1:9000
bash: php-cgi: command not found
root@9b4eb9cf9368:/var/www/html# php -S 0.0.0.0:8080 -t /var/www/html
[Wed Apr 2 22:10:42 2025] PHP 7.4.3-4ubuntu2.29 Development Server (http://0.0.0.0:8080) started
^Croot@9b4eb9cf9368:/var/www/html# SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET php-cgi -b 127.0.0.1:9000
bash: php-cgi: command not found

时间: 2025-04-02T22:12:17


🤖 DeepSeek (deepseek-chat)

The server is busy. Please try again later.

时间: 2025-04-02T22:12:17


👤 用户

root@9b4eb9cf9368:/var/www/html# nano
root@9b4eb9cf9368:/var/www/html# ss -tulnp | grep 80
tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:((“nginx”,pid=1,fd=6))
tcp LISTEN 0 128 [::]:80 [::]:* users:((“nginx”,pid=1,fd=7))
root@9b4eb9cf9368:/var/www/html# SCRIPT_NAME=/index.php \

SCRIPT_FILENAME=/var/www/html/index.php
REQUEST_METHOD=GET
php-cgi -b 127.0.0.1:9000
bash: php-cgi: command not found
root@9b4eb9cf9368:/var/www/html# php -S 0.0.0.0:8080 -t /var/www/html
[Wed Apr 2 22:10:42 2025] PHP 7.4.3-4ubuntu2.29 Development Server (http://0.0.0.0:8080) started
^Croot@9b4eb9cf9368:/var/www/html# SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET php-cgi -b 127.0.0.1:9000
bash: php-cgi: command not found

时间: 2025-04-02T22:13:31


🤖 DeepSeek (deepseek-chat)

The server is busy. Please try again later.

时间: 2025-04-02T22:13:31


👤 用户

root@9b4eb9cf9368:/var/www/html# nano
root@9b4eb9cf9368:/var/www/html# ss -tulnp | grep 80
tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:((“nginx”,pid=1,fd=6))
tcp LISTEN 0 128 [::]:80 [::]:* users:((“nginx”,pid=1,fd=7))
root@9b4eb9cf9368:/var/www/html# SCRIPT_NAME=/index.php \

SCRIPT_FILENAME=/var/www/html/index.php
REQUEST_METHOD=GET
php-cgi -b 127.0.0.1:9000
bash: php-cgi: command not found
root@9b4eb9cf9368:/var/www/html# php -S 0.0.0.0:8080 -t /var/www/html
[Wed Apr 2 22:10:42 2025] PHP 7.4.3-4ubuntu2.29 Development Server (http://0.0.0.0:8080) started
^Croot@9b4eb9cf9368:/var/www/html# SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET php-cgi -b 127.0.0.1:9000
bash: php-cgi: command not found

时间: 2025-04-02T22:14:49


🤖 DeepSeek (deepseek-chat)

根据最新的测试结果,我们发现容器内缺少 php-cgi 命令,这解释了为什么 PHP-FPM 无法正常处理请求。以下是终极解决方案:


🔧 终极修复步骤

1. 安装 php-cgi

在容器内执行:

1
apt-get update && apt-get install -y php7.4-cgi

2. 验证 PHP-FPM 配置

确认 /etc/php/7.4/fpm/pool.d/www.conf 包含:

1
2
3
4
listen = 127.0.0.1:9000
user = www-data
group = www-data
security.limit_extensions = .php

3. 强制测试 FastCGI

1
2
3
SCRIPT_FILENAME=/var/www/html/index.php \
REQUEST_METHOD=GET \
php-cgi -b 127.0.0.1:9000

4. 修改 Nginx 配置

确保 /etc/nginx/conf.d/default.conf 包含:

1
2
3
4
5
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

5. 重启服务

1
2
service nginx restart
service php7.4-fpm restart

📌 验证方法

  1. 测试 FastCGI

    1
    2
    # 在容器内执行
    SCRIPT_FILENAME=/var/www/html/index.php REQUEST_METHOD=GET php-cgi -b 127.0.0.1:9000
  2. 测试 Nginx

    1
    curl -v "http://localhost:8085/index.php"
  3. 检查日志

    1
    tail -f /var/log/nginx/error.log /var/log/php7.4-fpm.log

🚨 常见问题解决

问题 解决方案
php-cgi: command not found 安装 php7.4-cgi
FastCGI 通信失败 检查 fastcgi_pass 地址
文件权限问题 chown -R www-data:www-data /var/www/html

请先安装 php-cgi 后继续测试,如果仍有问题,请提供:

  1. apt-get install php7.4-cgi 的输出
  2. 安装后 php-cgi -v 的结果
  3. 新的测试结果

时间: 2025-04-02T22:14:49



对话统计

  • 消息总数: 40 条
  • 处理状态: 成功转换