【问题标题】:How do I get PHP-FPM to work with nginx-proxy with FastCGI?如何让 PHP-FPM 与 FastCGI 的 nginx-proxy 一起工作?
【发布时间】:2020-07-15 17:26:59
【问题描述】:

我试图通过fastcginginx-proxythe official php imagephp-fpm 变体一起工作。不幸的是,我似乎无法这样做。我确定问题只是一些我不知道的简单问题。

我已尽我所能关注 the instructions 的 nginx-proxy,并将其归结为一种非常简单的方法来重新创建问题。这是我的docker-compose.yml 文件:

version: "3"

services:
  proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
    environment:
      - DEFAULT_HOST=test.local

  fpm:
    image: php:fpm
    environment:
      - VIRTUAL_HOST=test.local
      - VIRTUAL_PROTO=fastcgi

然后我通过运行放入一个简单的index.php 文件:

docker container exec -it web_fpm_1 /bin/bash -c 'echo "<?php phpinfo(); ?>" > /var/www/html/index.php'

(它把web_放在前面,因为这个项目在一个名为web/的目录中。)

我还将我的hosts 文件修改为将test.local 指向127.0.0.1,所以我可以对其进行测试。 但是,每次尝试浏览到 test.local 都会导致出现空白页。

据我所知,web_proxy_1 容器的日志没有任何异常之处:

❯ docker container logs web_proxy_1
WARNING: /etc/nginx/dhparam/dhparam.pem was not found. A pre-generated dhparam.pem will be used for now while a new one
is being generated in the background.  Once the new dhparam.pem is in place, nginx will be reloaded.
forego     | starting dockergen.1 on port 5000
forego     | starting nginx.1 on port 5100
dockergen.1 | 2020/07/20 19:24:54 Generated '/etc/nginx/conf.d/default.conf' from 2 containers
dockergen.1 | 2020/07/20 19:24:54 Watching docker events
dockergen.1 | 2020/07/20 19:24:54 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload'
nginx.1    | test.local 172.18.0.1 - - [20/Jul/2020:19:25:12 +0000] "GET / HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
nginx.1    | test.local 172.18.0.1 - - [20/Jul/2020:19:25:13 +0000] "GET /favicon.ico HTTP/1.1" 200 5 "http://test.local/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"

web_fpm_1 容器的日志显示除了 200 响应之外什么都没有发送:

❯ docker container logs web_fpm_1
[20-Jul-2020 19:24:54] NOTICE: fpm is running, pid 1
[20-Jul-2020 19:24:54] NOTICE: ready to handle connections
172.18.0.3 -  20/Jul/2020:19:25:12 +0000 "- " 200
172.18.0.3 -  20/Jul/2020:19:25:13 +0000 "- " 200

我做错了什么?

顺便说一句,我在nginx-proxy reponginx-proxy Google Groupphp repo 上问过这个问题。我要么没有回应,要么他们推卸责任。

【问题讨论】:

  • 试试curl http://test.local/var/www/html/index.php让我知道这是否可行
  • 能否请您显示 nginx 日志。
  • 您好,感谢您的回复。 @WSMathias9:恐怕结果什么都没有。它什么也不返回,就像转到页面本身返回一个空白页一样。 @丹尼尔:完成了。我已经编辑了原始帖子以包含代理的日志。
  • 让两个服务在docker-compose.yml 中通过volumes 共享/var/www/html/index.php/var/run/docker.sock:/tmp/docker.sock。走着瞧吧。您也可以将它们放在同一个网络中。
  • @BentCoder 这不是它应该配置的。不要只是尝试打开 777 并为一切付出一切,然后“看看会发生什么”。这就是您为黑客打开服务器并使系统不稳定的方式。非常糟糕的建议。数据只能在 1 个容器中。

标签: php docker fastcgi jwilder-nginx-proxy


【解决方案1】:

nginx-proxy 的默认生成配置未完全正常工作。

我认为VIRTUAL_ROOT environment variable 出了问题,因为问题的根源是 PHP 通过SCRIPT_FILENAME 获取了错误的路径(这就是为什么你看不到 PHP 输出)并且没有 try_files=404符号(这就是为什么你得到 200 的一切)。

我在 GitHub 中使用 docker-compose 进行了准备工作设置,以证明它可以与 nginx 配置中的现有 SCRIPT_FILENAME 一起使用。

我已将test.local 更改为test.localhost

我认为要使其正常工作,您必须为 nginx-proxy 使用 nginx 模板,因此生成的 default.conf 确实适用于 php fpm 并包含缺少的 fastcgi 参数。

另一种不同的方法是将 PHP 和手动配置的网络服务器 (nginx) 打包到一个项目中,并在一个独立的项目中使用自动反向 nginx 代理。 这会花费您额外的进程运行时间,但会为您提供更多控制和更轻松的部署。

或者,您可能想查看traefik,它与nginx-proxy 基本相同。

【讨论】:

  • 好的,@Daniel,这让我比以往任何时候都更接近让 nginx-proxy 在 fastcgi 上工作。至少,我现在得到了一个“欢迎使用 nginx”页面。您的 github 存储库很有效,并且在大多数情况下确实突出了我需要做的事情。但是,我仍然想知道如何让它与多个服务器一起使用。看来我需要关注 jwilder 的virtual host instructions。我是否只是将整个 server {} 块复制到 vhost 文件中?
  • 另外,我查看了 traefik。看起来它值得进一步研究,但由于我已经使用 nginx-proxy 到目前为止,我想先完成这个任务。
  • 当 nginx-proxy 正在监听 docker 套接字/var/run/docker.sock:/tmp/docker.sock:ro 时,奇迹正在发生。代理可以看到您何时加载新容器并自动重新生成自己的 nginx 配置。 nginx-proxy 使用环境变量VIRTUAL_...,而 traefik 使用所谓的labels。您应该尝试更改 nginx-proxy 模板并为您自己提供缺少的 SCRIPT_FILENAME 或者您更改 nginx fastcgi_params 以包含 SCRIPT_FILENAME
  • @Sturm 我在笔记本上使用 traefik 进行本地开发,在生产系统上使用 nginx(手动配置)。 “自动配置”的东西只有在本地或在开发时才真正有用,但手动配置也不错。
  • 所以我猜你认为我不应该遵循虚拟主机的说明? “您应该尝试更改 nginx-proxy 模板并为您自己的模板提供缺少的 SCRIPT_FILENAME,或者您更改 nginx fastcgi_params 以包含 SCRIPT_FILENAME” - 恐怕我不知道在哪里/如何执行此操作。您能否修改您的答案以包含有关如何更新代理模板的说明?
【解决方案2】:

Daniel 的回答绝对是正确的。我使用带有 nginx 的 php-fpm 图像作为 php 站点的主要堆栈。话虽如此,我不使用 nginx-proxy docker 镜像。相反,我在主机上使用纯 nginx,并将端口配置为指向后端 php-fpm docker 图像。

我也没有使用 docker-compose。因为它只是运行单个站点的 docker 容器,所以我不需要它。这是一个示例 docker run 命令:

docker rm -f www.example.com || true
docker run -itd -p 9001:9000 -P \
        --name www.example.com \
        --volume /var/www/html/www.example.com:/var/www/html/www.example.com \
        --link mariadb:database.example.com \
        --restart="always" \
        --hostname="example.com" \
    --log-opt max-size=2m \
    --log-opt max-file=5 \
        mck7/php-fpm:7.4.x-wordpress

这是一个示例 nginx 配置:

server {
  server_name example.com www.example.com;

  location ~ /.well-known {
    allow all;
  }

  location ~ /\.ht {
    deny all;
  }

  root /var/www/html/www.example.com/src;

  index index.php;

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

  location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
      return 404;
    }

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

    fastcgi_pass   127.0.0.1:9001;
    fastcgi_index  index.php;
  }
}

有关此设置的一些事项是关键。 docker 容器的端口重新映射。在本例中,我将端口 9001 映射到 9000。另一个“陷阱”是容器的根必须是主机上的实际位置。我不知道为什么会这样,但无论出于何种原因,docker 认为它正在使用的路径实际上也必须是主机上的路径。

【讨论】:

    猜你喜欢
    • 2015-04-29
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 2020-04-29
    • 2017-01-19
    • 2011-03-12
    • 1970-01-01
    • 2017-06-25
    相关资源
    最近更新 更多