Nginx Docker 容器 403 错误排查与解决方案
问题描述
在飞牛 NAS 上使用 Docker 部署 Nginx 静态网站时,访问 http://IP:8080 出现 403 Forbidden 错误。
环境信息
- NAS 系统:飞牛 NAS
- 容器镜像:nginx:alpine
- 端口映射:8080:80
- 目录结构:
/vol1/1001/workspace/subcatcher/
├── dist/
│ ├── index.html
│ └── assets/
├── docker-compose.yml
└── nginx.conf
问题排查过程
1. 查看容器日志
# 查看 Nginx 错误日志
sudo docker exec subcatcher-aesthetic cat /var/log/nginx/error.log
关键错误信息:
[error] 22#22: *1 open() "/usr/share/nginx/html/index.html" failed (13: Permission denied)
2. 检查容器内文件权限
sudo docker exec subcatcher-aesthetic ls -la /usr/share/nginx/html/
发现问题:
-rw-rwx--- 1 1001 root 1385 Jan 23 11:57 index.html
drwxrwx--- 1 1001 root 70 Jan 23 11:58 assets
- 文件所有者是
1001:root - 文件权限是
670(只有所有者和组有读写权限) - Nginx worker 进程无法读取文件
根本原因
文件权限不足:宿主机上 dist 目录的文件权限不正确,导致容器内 Nginx 进程(即使以 root 运行)无法读取挂载的文件。
解决方案
✅ 方案一:修复文件权限(推荐)
这是最直接、最彻底的解决方法。
# 1. 修改文件权限为 755(所有用户可读可执行)
sudo chmod -R 755 /vol1/1001/workspace/subcatcher/dist
# 2. 重启容器使权限生效
sudo docker restart subcatcher-aesthetic
# 3. 验证是否解决
sudo docker logs subcatcher-aesthetic --tail 20
权限说明:
755=rwxr-xr-x- 所有者:读写执行
- 组用户:读执行
- 其他用户:读执行
方案二:修改容器运行用户
如果不想改变文件权限,可以让容器以文件所有者身份运行。
修改 docker-compose.yml:
services:
subcatcher:
image: nginx:alpine
container_name: subcatcher-aesthetic
user: "1001:1001" # 匹配文件所有者 UID:GID
restart: always
ports:
- "8080:80"
volumes:
- ./dist:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
environment:
- TZ=Asia/Shanghai
networks:
- subcatcher-net
重启:
sudo docker-compose down
sudo docker-compose up -d
方案三:去掉只读挂载
将卷挂载从只读改为读写(不推荐用于生产环境)。
volumes:
- ./dist:/usr/share/nginx/html # 去掉 :ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
常用排查命令
Docker 权限问题
# 如果遇到 "permission denied while trying to connect to docker API"
sudo docker <command>
# 或将用户添加到 docker 组
sudo usermod -aG docker $USER
newgrp docker
查看容器日志
# 查看完整日志
sudo docker logs subcatcher-aesthetic
# 只看最后 20 行
sudo docker logs subcatcher-aesthetic --tail 20
# 实时查看日志
sudo docker logs -f subcatcher-aesthetic
进入容器调试
# 进入容器 Shell
sudo docker exec -it subcatcher-aesthetic sh
# 在容器内检查文件
ls -la /usr/share/nginx/html/
cat /usr/share/nginx/html/index.html
# 查看 Nginx 配置是否正确
nginx -t
# 查看错误日志
cat /var/log/nginx/error.log
检查宿主机权限
# 查看目录权限
ls -la /vol1/1001/workspace/subcatcher/
ls -la /vol1/1001/workspace/subcatcher/dist/
# 修复权限
sudo chmod -R 755 /vol1/1001/workspace/subcatcher/dist/
sudo chown -R root:root /vol1/1001/workspace/subcatcher/dist/
预防措施
1. 构建镜像时设置正确权限
如果使用自定义 Dockerfile:
FROM nginx:alpine
COPY --chown=nginx:nginx dist/ /usr/share/nginx/html/
RUN chmod -R 755 /usr/share/nginx/html/
EXPOSE 80
2. 部署前检查清单
# ✓ 检查文件是否存在
ls -la ./dist/index.html
# ✓ 检查文件权限(应为 644 或 755)
stat -c "%a %n" ./dist/index.html
# ✓ 测试 Nginx 配置语法
sudo docker exec subcatcher-aesthetic nginx -t
# ✓ 查看容器是否正常运行
sudo docker ps | grep subcatcher
3. 标准化部署流程
#!/bin/bash
# deploy.sh - 标准化部署脚本
# 1. 确保权限正确
chmod -R 755 ./dist/
# 2. 停止旧容器
docker-compose down
# 3. 启动新容器
docker-compose up -d
# 4. 检查运行状态
docker-compose ps
docker-compose logs --tail 20
# 5. 测试访问
curl -I http://localhost:8080
完整配置文件参考
docker-compose.yml
services:
subcatcher:
image: nginx:alpine
container_name: subcatcher-aesthetic
user: root # 或使用具体 UID,如 "1001:1001"
restart: always
ports:
- "8080:80"
volumes:
- ./dist:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
environment:
- TZ=Asia/Shanghai
networks:
- subcatcher-net
networks:
subcatcher-net:
driver: bridge
nginx.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gzip 压缩
gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml+rss text/javascript;
gzip_vary on;
# SPA 路由支持
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
}
# 静态资源缓存
location ~* .(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# 安全响应头
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
}
总结
Nginx 403 错误的核心原因:文件权限问题
最佳解决方案:
- 使用
chmod -R 755确保文件可读 - 重启容器使挂载生效
- 建立标准化部署流程避免重复问题
关键命令:
sudo chmod -R 755 /path/to/dist
sudo docker restart container-name
sudo docker logs container-name