使用PHP-FPM和Docker部署Symfony时出现404 File not found问题求助
从昨天开始部署Symfony应用到个人服务器(拥有全部权限,但Linux相关知识有限),已将服务器8002端口映射到容器9000端口,Docker日志显示请求已到达容器,但所有请求均返回404 File not found错误,所有端点均出现该问题。
配置文件
subdomain.conf
<VirtualHost *:80> ServerName mysubdomain.domain.com ServerAlias www.mysubdomain.domain.com # Redirect to HTTPS RewriteEngine on RewriteCond %{SERVER_NAME} =mysubdomain.domain.com [OR] RewriteCond %{SERVER_NAME} =www.mysubdomain.domain.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost> <VirtualHost *:443> ServerName mysubdomain.domain.com ServerAlias www.mysubdomain.domain.com # Proxy settings ProxyPreserveHost On ProxyPass / fcgi://localhost:8002/ ProxyPassReverse / fcgi://localhost:8002/ DocumentRoot /var/www/html/project/project-back/public DirectoryIndex /index.php # Allow .htaccess overrides in the public directory <Directory /var/www/html/project/project-back/public> AllowOverride All Options FollowSymLinks Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/mysubdomain.domain.com-error.log CustomLog ${APACHE_LOG_DIR}/mysubdomain.domain.com-access.log combined # Enable SSL SSLEngine on SSLCertificateFile /some/path SSLCertificateKeyFile /some/path Include /some/path # Optionally enable HSTS to force browsers to use HTTPS Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" </VirtualHost>
Dockerfile
# Use the official PHP 8.1 FPM image as the base FROM php:8.1-fpm # Set the working directory inside the container WORKDIR /var/www/html # Install system dependencies RUN apt-get update && apt-get install -y \ git \ unzip \ nano \ net-tools \ lsof \ libpq-dev \ libzip-dev \ && docker-php-ext-install pdo pdo_mysql zip # Install Composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Copy project files into the container COPY . . # Set permissions for cache and log directories RUN chmod -R 777 /var/www/html/var/cache /var/www/html/var/log # Set permissions for cache and log directories RUN chmod -R 777 /var/www/html/public # Install Symfony dependencies RUN composer install --no-dev --optimize-autoloader # Expose PHP-FPM port EXPOSE 9000 # Start PHP-FPM CMD ["php-fpm", "-F"]
docker-compose.yaml
services: php: build: context: . dockerfile: ./Dockerfile container_name: mycontainer volumes: - .:/var/www/html - ./public:/var/www/html/public working_dir: /var/www/html ports: - "8002:9000" networks: - database networks: database: external: true
调试信息
数据库网络连接正常,已在其他项目中使用。
最初mysubdomain.domain.com-error.log中存在警告:
[proxy:warn] AH01144: No protocol handler was valid for the URL / (scheme 'fcgi'). If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.
已通过sudo a2enmod proxy_fcgi解决该警告,但现在访问子域名时会出现404 File not found错误。
服务器端命令输出
$ curl https://mysubdomain.domain.com/ File not found.
$ curl -I https://mysubdomain.domain.com/ HTTP/1.1 404 Not Found Date: Sat, 30 Nov 2024 14:48:08 GMT Server: Apache/2.4.62 (Debian) X-Powered-By: PHP/8.1.31 Content-Type: text/html; charset=UTF-8
$ curl -I http://localhost:8002 curl: (52) Empty reply from server
$ sudo docker logs mycontainer NOTICE: fpm is running, pid 1 NOTICE: ready to handle connections "GET /" 404 "GET /" 404 "GET /" 404 "GET /" 404
容器内部命令输出
# curl -I http://localhost:9000 curl: (56) Recv failure: Connection reset by peer
netstat -tlnp | grep 9000 tcp6 0 0 :::9000 :::* LISTEN 1/php-fpm
补充说明:遇到的不是普通的“404 page not found”,而是“404 File not found”,所有页面都只显示这个内容,没有其他错误日志。
解决方案
核心问题分析
这个File not found是PHP-FPM返回的,原因是Apache传递给FPM的文件路径在容器内不存在:Apache的DocumentRoot指向服务器本地的/var/www/html/project/project-back/public,但容器内的项目路径是/var/www/html/public,两者路径不匹配,导致FPM找不到请求对应的文件。同时,直接用ProxyPass / fcgi://localhost:8002/的写法无法正确传递PHP文件的路径信息。
修复步骤
修改Apache配置文件
subdomain.conf
在VirtualHost *:443块中,替换原有的Proxy相关配置,改用ProxyPassMatch来正确映射容器内的文件路径:# 替换原有ProxyPass/ProxyPassReverse配置 # 仅转发PHP请求到FPM,并映射到容器内的正确路径 ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://localhost:8002/var/www/html/public/$1 # 静态文件直接从本地目录提供(提升性能) DocumentRoot /var/www/html/project/project-back/public <Directory /var/www/html/project/project-back/public> AllowOverride All Options FollowSymLinks Require all granted # Symfony前端控制器转发规则,处理非文件请求 RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /index.php [QSA,L] </Directory>清理Docker重复Volume映射
修改docker-compose.yaml,移除重复的./public映射(因为.:/var/www/html已经包含了public目录):volumes: - .:/var/www/html # 移除 - ./public:/var/www/html/public优化容器权限(可选但推荐)
修改Dockerfile中的权限设置,避免使用过高的777权限,改用www-data用户权限:# 替换原有的chmod命令 RUN chown -R www-data:www-data /var/www/html/var /var/www/html/public RUN chmod -R 755 /var/www/html/var /var/www/html/public重启服务并重建容器
# 重启Apache sudo systemctl restart apache2 # 重建并启动容器 docker-compose down && docker-compose up -d --build
完成以上步骤后,重新访问子域名即可正常加载Symfony应用。
内容的提问来源于stack exchange,提问作者Anis B.

