Docker环境下Nginx与php-fpm容器静态文件访问location配置问题
问题核心原因
- Nginx的
root指令仅能读取当前容器本地文件系统的文件,无法直接读取php-fpm容器内的文件,你配置的root api:9000/public/vendor/语法完全不生效 - FastCGI协议默认仅用于执行PHP脚本,直接转发静态资源请求到php-fpm时,php-fpm没有对应处理逻辑,无法返回静态文件内容
推荐解决方案(生产环境最优)
使用共享挂载卷实现两个容器文件同步,这是性能最高的方案,Nginx可以直接读取本地静态文件,不需要走php-fpm转发:
- 调整docker-compose.yml(或者docker run命令),将项目目录同时挂载到两个容器的相同路径,示例:
services: api: # 你的php-fpm服务名 image: php:fpm volumes: - ./你的本地项目目录:/app/api/public # 挂载到php-fpm容器 nginx: image: nginx:alpine volumes: - ./你的本地项目目录:/app/api/public # 同路径挂载到nginx容器 - ./你的nginx配置文件路径:/etc/nginx/conf.d/default.conf
- 修改Nginx配置,删除原来错误的静态资源location规则,替换为以下配置:
server { listen 80 default_server; root /app/api/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } # 静态资源规则,直接从本地挂载目录读取 location ~ ^/(static|vendor)/ { expires 30d; # 添加静态资源缓存,优化访问速度 add_header Cache-Control "public, no-transform"; } location ~ \.php$ { include fastcgi_params; fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_index index.php; fastcgi_intercept_errors on; fastcgi_pass api:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_read_timeout 3600; } }
- 重启两个容器即可生效。
临时调试方案(不推荐生产使用)
如果不想配置共享挂载,可以通过PHP脚本中转处理静态资源请求:
- 在php-fpm容器的
/app/api/public目录下新建static_handler.php文件,内容如下:
<?php // 允许访问的静态资源目录 $allowedDirs = ['static', 'vendor']; $requestPath = ltrim($_SERVER['REQUEST_URI'], '/'); $pathParts = explode('/', $requestPath); // 校验路径合法性 if (!in_array($pathParts[0], $allowedDirs)) { http_response_code(403); exit('Forbidden'); } // 拼接php-fpm容器内的绝对路径 $fullPath = __DIR__ . '/' . $requestPath; if (!file_exists($fullPath) || is_dir($fullPath)) { http_response_code(404); exit('Not Found'); } // 输出正确的Content-Type $mimeTypes = [ 'css' => 'text/css', 'js' => 'application/javascript', 'png' => 'image/png', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'svg' => 'image/svg+xml', 'woff' => 'font/woff', 'woff2' => 'font/woff2', ]; $ext = pathinfo($fullPath, PATHINFO_EXTENSION); header('Content-Type: ' . ($mimeTypes[$ext] ?? 'application/octet-stream')); header('Content-Length: ' . filesize($fullPath)); readfile($fullPath); exit;
- 修改Nginx配置的静态资源location规则:
location ~ ^/(static|vendor)/ { include fastcgi_params; fastcgi_pass api:9000; fastcgi_param SCRIPT_FILENAME /app/api/public/static_handler.php; fastcgi_param REQUEST_URI $request_uri; }
- 重启Nginx即可生效。
内容的提问来源于stack exchange,提问作者Maciej
相关产品推荐
相关产品推荐

