【问题标题】:Apache 404 FilesMatchApache 404 文件匹配
【发布时间】:2021-08-22 16:05:01
【问题描述】:

考虑以下有效的 Apache 配置(在 httpd:2.4.48-alpine docker 容器中使用)

<VirtualHost *:80>
   
   DocumentRoot "/code2"

   <Proxy "fcgi://php/">
       ProxySet enablereuse=On
   </Proxy>

   <FilesMatch \.php$>
       SetHandler "proxy:fcgi://php:9000"
   </FilesMatch>

   <Directory /code2>
       Options Indexes FollowSymLinks
       AllowOverride All
       Require all granted
   </Directory>

   DirectoryIndex index.php

</VirtualHost>

但是,如果我将与 php-fpm 容器(名为“php”)中的路径匹配的 /code2 目录移动到例如:/code(我还更新了 DocumentRoot 和目录路径)。

我在所有 php 文件上都收到 404。为什么会这样?如何为每个容器提供不同的 php 文件路径?

另一个需要注意的有趣的事情是apache和php的访问日志都没有显示正在访问的php文件的完整路径,只有文件名。

【问题讨论】:

    标签: php docker apache httpd.conf


    【解决方案1】:

    如果您想在 PHP 处理程序中使用“DocumentRoot”指令,您还需要将该卷挂载到httpd。默认情况下,不存在的文件会直接触发404(见https://cwiki.apache.org/confluence/display/HTTPD/PHP-FPM“Proxy via handler”)

    这是一个用于您的用例的小示例(为简单起见使用 docker-compose):

    ./docker-compose.yaml:

    version: "3.9"
    
    services:
      httpd:
        build:
          context: ./httpd/
        ports:
          - 80:80
        volumes:
          - ./php-vol:/code2:rw
      php:
        image: php:8.0-fpm
        volumes:
          - ./php-vol:/code2:rw
          - ./php-vol2:/code2/another-dir:rw
    

    ./httpd/Dockerfile

    FROM httpd:2.4.48-alpine
    
    COPY php-fpm.conf conf/extra/php-fpm.conf
    
    RUN echo "Include conf/extra/php-fpm.conf" >> conf/httpd.conf
    
    RUN sed -i \
            -e 's/^#\(LoadModule .*mod_proxy.so\)/\1/' \
            -e 's/^#\(LoadModule .*mod_proxy_fcgi.so\)/\1/' \
            conf/httpd.conf
    

    ./httpd/php-fpm.conf(使用 PHP 处理程序,请参阅https://cwiki.apache.org/confluence/display/HTTPD/PHP-FPM

    <VirtualHost *:80>
       DocumentRoot "/code2"
    
       <Proxy "fcgi://php/">
           ProxySet enablereuse=On
       </Proxy>
    
       <FilesMatch \.php$>
           SetHandler "proxy:fcgi://php:9000"
       </FilesMatch>
       
       <Directory /code2>
           Options Indexes FollowSymLinks
           AllowOverride All
           Require all granted
       </Directory>
    
       DirectoryIndex index.php
    </VirtualHost>
    

    如果您只想使用 php-fpm 提供 .php 文件,则可以简化:

    <VirtualHost *:80>
       ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/code2/$1
    
       DirectoryIndex index.php
    </VirtualHost>
    

    【讨论】:

    • 所以回答你的问题“我怎样才能为每个容器提供不同的 php 文件路径?”是:php-fpm和httpd之间不能有不同的路径。
    • 这类似于我提供的工作示例,我为非 php 文件提供了 DocumentRoot。我希望路径不同,因为这将允许一个通用容器而不是多个副本。我没有看到我的工作示例有任何功能差异,所以我不认为这是一个答案。我想将文件安装在不同的位置。使用 nginx,我提供了一个相对路径并为其添加了不同的根前缀。使用 apache 这应该是默认的?
    • 如果您说的不可能,但是这是一个有效的答案。你确定吗? DirectoryPath 没用?
    • 是的,如果您希望 Apache 直接提供静态文件,我确信 DocumentRoot Apache 与 php-fpm 必须相等。我在上面的示例中添加了另一个 PHP 卷,将其安装在 DocumentRoot 内的某个位置——也许这更适合您的用例?接下来你可以研究的是一个额外的 php-fpm 池,但这当然需要另一个 Apache VirtualHost(带有另一个 DocumentRoot)。
    • 您能否添加一个更完整的示例,说明您希望从哪个卷和哪个服务 (apache/php-fpm) 提供哪些 URL 路径?
    【解决方案2】:

    如果您想在 httpd 和 php-fpm 中使用不同的路径,您可以使用 ProxyFCGISetEnvIf 自定义发送到 php-fpm 的环境变量。

    https://httpd.apache.org/docs/2.4/mod/mod_proxy_fcgi.html#proxyfcgisetenvif

    不幸的是,php-fpm 可能会查看变量组合以确定在磁盘上查看的位置可能有点令人困惑——这实际上是该指令存在的原因,它让您有机会在最后一刻查看 mod_proxy_fcgi 会有什么发送然后调整它们。

    手册中的这个示例非常接近您的问题(删除了 \d 后缀):

    ProxyFCGISetEnvIf "reqenv('PATH_TRANSLATED') =~ m|(/.*prefix)(\d+)(.*)|" PATH_TRANSLATED "$1$3"
    

    我建议使用此模式将 PATH_TRANSLATED(文件系统路径)从您的 httpd 容器转换为在 FPM 容器中有效的路径。

    【讨论】:

    • 我最后一次看这个(可能是为了实现 ProxyFCGISetEnvIf)我发现这个转储变量的假 FPM 服务器很有用:hastebin.com/xexexomubi.php
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多