Docker环境下Nginx容器无法加载静态文件求助
问题:Laravel项目Docker部署后静态文件404排查
背景信息
- 基于
composer:2.7.7和php:8.3.3-fpm-alpine3.19构建Docker镜像,镜像内安装node.js及依赖,执行composer update、composer install、npm install vite、npm run build并设置文件权限 - 配置docker-compose.yml,包含PHP-FPM、Nginx、MySQL服务
- 编写Nginx配置尝试路由静态文件,但浏览器控制台出现静态文件404错误,不确定是否需要挂载静态文件卷
相关配置文件
Dockerfile
FROM composer:2.7.7 FROM php:8.3.3-fpm-alpine3.19 # Install required packages RUN apk add --no-cache nodejs npm RUN docker-php-ext-install pdo_mysql COPY --chown=www-data:www-data . /var/www/html COPY --from=0 /usr/bin/composer /usr/bin/composer # Ensure permissions are set correctly RUN chmod -R 755 /var/www/html/public/build/assets USER www-data #composer run commands RUN composer update RUN composer install #npm run commands RUN npm install vite RUN npm run build USER root
docker-compose.yml
version: '3.8' services: rental-project: image: rental-project:0.14.0 container_name: rental-project env_file: - .env networks: - rentalProject-api-network web-server: image: nginx:1.24.0-alpine-slim container_name: web-server ports: - "8080:80" volumes: - ./laravel.conf:/etc/nginx/conf.d/default.conf networks: - rentalProject-api-network mysql: image: mysql:latest container_name: mysql_container environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: rentalProject MYSQL_USER: rentalProject MYSQL_PASSWORD: secret volumes: - mysql_data:/var/lib/mysql - ./dumps:/docker-entrypoint-initdb.d networks: - rentalProject-api-network volumes: mysql_data: networks: rentalProject-api-network:
Nginx配置文件(laravel.conf)
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; index index.php; charset utf-8; location / { try_files $uri $uri /index.php?$query_string; } location /assets { alias /var/www/html/public/build/assests; autoindex on; autoindex_exact_size off; autoindex_localtime on; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass rental-project:9000; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } }
问题排查及解决方案
1. Nginx配置拼写错误
Nginx的/assets location块中,alias路径写为/var/www/html/public/build/assests——assets拼写成了assests,少了一个s,这是直接导致404的核心原因,修正后:
location /assets { alias /var/www/html/public/build/assets; autoindex on; autoindex_exact_size off; autoindex_localtime on; }
2. Nginx无法访问PHP容器内的静态文件
当前docker-compose中,Nginx容器未挂载PHP容器内的静态文件目录,Nginx自身容器不存在/var/www/html/public/build/assets路径,即使修正拼写也无法找到文件。
解决方式有两种:
方式一:共享静态文件目录(推荐)
在docker-compose.yml中添加命名卷,让PHP和Nginx共享静态文件目录:services: rental-project: # 其他配置不变 volumes: - rental-project-static:/var/www/html/public/build/assets web-server: # 其他配置不变 volumes: - ./laravel.conf:/etc/nginx/conf.d/default.conf - rental-project-static:/var/www/html/public/build/assets # 新增命名卷 volumes: mysql_data: rental-project-static:方式二:通过PHP-FPM转发静态文件(临时方案)
删除单独的/assetslocation块,依赖根路径的try_files规则让PHP-FPM处理静态请求,但会增加PHP-FPM负载,不建议生产环境使用。
3. 静态文件卷挂载的必要性
- 开发环境:需要挂载本地
public/build/assets目录到容器,方便修改前端代码后实时生效:rental-project: volumes: - ./public/build/assets:/var/www/html/public/build/assets web-server: volumes: - ./laravel.conf:/etc/nginx/conf.d/default.conf - ./public/build/assets:/var/www/html/public/build/assets - 生产环境:静态文件已在镜像构建时生成,无需挂载卷,通过共享命名卷让Nginx访问镜像内的静态文件即可。
4. Dockerfile优化建议
- 生产环境建议使用
composer install配合composer.lock文件,替代composer update,保证依赖版本一致。 - 将
vite添加到项目package.json的依赖中,直接执行npm install即可,无需单独安装。
内容的提问来源于stack exchange,提问作者SaTown
相关产品推荐
相关产品推荐

