Docker部署VueJS应用Nginx报403目录索引禁止及503错误
问题现象
- 使用Nginx容器化部署VueJS应用时服务持续报错,Nginx错误日志重复输出以下内容:
[error] 8#8: *1 directory index of "/etc/nginx/html/" is forbidden, client: x.x.x.x, server: localhost, request: "GET / HTTP/1.1", host: "x.x.x.x:80"
- 浏览器访问服务返回
503 Service Temporarily Unavailable - nginx提示
现有配置
Dockerfile
FROM nginx:1.17-alpine # Copy built app into nginx COPY /dist /etc/nginx/html/studio # copy nginx conf COPY nginx.conf /etc/nginx/nginx.conf
nginx.conf
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; sendfile on; keepalive_timeout 65; map $http_user_agent $loggable { "~kube-probe/.*" 0; default 1; } access_log /var/log/nginx/access.log main if=$loggable; server { listen 80; server_name localhost; location /studio/ { try_files $uri $uri/ /studio/index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
根因分析
- 根路径无匹配规则:当前配置仅为
/studio/路径设置了路由规则,访问根路径/时Nginx会 fallback 到默认静态目录查找资源,该路径下没有配置默认首页index.html,同时未开启目录列表权限,因此抛出directory index is forbidden错误。 - 缺少显式root配置:
/studio/的location块未指定静态资源根目录,Nginx自动拼接路径时会出现寻址偏差,即使直接访问/studio/路径也可能找不到对应文件。 - 子路径部署适配缺失:如果要把应用部署在
/studio/子路径下,Vue构建时的publicPath参数未同步配置,会导致静态资源加载失败。
排查思路
- 先进入运行中的容器执行
ls /etc/nginx/html/studio,确认index.html、js/css/img等静态资源是否存在,排除Docker COPY命令执行错误导致的文件缺失问题。 - 检查Nginx配置中所有对外暴露的访问路径是否都有对应的location匹配规则,重点确认根路径
/的处理逻辑。 - 核对location块内root/alias配置与实际文件存放路径是否一致,避免路径拼接错误。
- 如果使用Vue Router的history模式,确认try_files规则是否正确配置,避免刷新页面出现403/404错误。
- 若部署在K8s集群中,额外检查Service是否正确关联Pod端口、Ingress转发规则是否配置正确,排除网络层面的转发故障。
修复方案
根据实际部署需求二选一即可:
场景1:应用部署在根路径(直接访问IP/域名即可打开应用)
- 修改Dockerfile,将构建产物复制到Nginx官方镜像默认的静态资源目录:
FROM nginx:1.17-alpine # 把dist目录下的所有文件直接复制到nginx默认静态目录 COPY /dist /usr/share/nginx/html/ COPY nginx.conf /etc/nginx/nginx.conf # 修正静态目录权限,避免nginx用户无读权限 RUN chown -R nginx:nginx /usr/share/nginx/html
- 修改nginx.conf,补充根路径路由规则、显式指定root目录:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; sendfile on; keepalive_timeout 65; map $http_user_agent $loggable { "~kube-probe/.*" 0; default 1; } access_log /var/log/nginx/access.log main if=$loggable; server { listen 80; server_name localhost; # 显式指定静态资源根目录 root /usr/share/nginx/html; index index.html; # 关闭目录索引,避免安全风险 autoindex off; # 根路径适配Vue Router history模式 location / { try_files $uri $uri/ /index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }
- 确认Vue项目
vue.config.js中publicPath配置为'/'(默认值即为/,未修改过则无需调整),重新执行npm run build生成最新dist包后构建镜像即可。
场景2:应用部署在/studio/子路径(访问IP/studio/打开应用)
- 原有Dockerfile的复制逻辑无需调整,补充权限修正命令即可:
FROM nginx:1.17-alpine COPY /dist /etc/nginx/html/studio COPY nginx.conf /etc/nginx/nginx.conf RUN chown -R nginx:nginx /etc/nginx/html
- 修改nginx.conf,补充根路径跳转规则、子路径root配置:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; sendfile on; keepalive_timeout 65; map $http_user_agent $loggable { "~kube-probe/.*" 0; default 1; } access_log /var/log/nginx/access.log main if=$loggable; server { listen 80; server_name localhost; root /etc/nginx/html; index index.html; autoindex off; # 访问根路径时自动跳转到子路径 location = / { return 302 /studio/; } # 子路径适配Vue Router history模式 location /studio/ { try_files $uri $uri/ /studio/index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /etc/nginx/html; } } }
- 修改Vue项目
vue.config.js,配置publicPath匹配子路径:
module.exports = { publicPath: '/studio/' }
重新执行npm run build生成最新dist包后构建镜像即可。
内容的提问来源于stack exchange,提问作者Khalil Azennoud
相关产品推荐
相关产品推荐

