Nginx+Docker部署HTTPS时证书加载失败问题求助
问题分析
你的核心问题有两个:
- 软链接失效:CertBot在
/etc/letsencrypt/live/footeware.ca下的证书文件是软链接,指向/etc/letsencrypt/archive/footeware.ca中的真实证书文件。你只挂载了live/footeware.ca目录,容器内没有对应的archive目录,导致软链接无法解析,Nginx找不到真实文件。 - 权限不足:宿主机上
/etc/letsencrypt下的目录权限是drwx------(仅root可读),而Nginx容器默认以nginx用户(UID 101)运行,没有读取证书的权限。
解决方案
1. 修正Docker挂载路径
修改compose.yaml,挂载整个/etc/letsencrypt目录,让容器能访问到live和archive两个目录:
services: ng_web: image: craigfoote/ng.web:latest container_name: ng.web restart: unless-stopped ports: - 443:443 volumes: - /etc/letsencrypt:/etc/letsencrypt # 替换原来的仅挂载live子目录
2. 解决权限问题
方法一:以root用户运行容器(简单高效,适合个人服务器)
在compose.yaml中添加user: root,让Nginx以root权限读取证书:
services: ng_web: ... user: root ...
方法二:调整宿主机证书目录权限(更安全)
给容器内的nginx用户(默认UID 101)授予证书目录的读取权限:
# 给live和archive目录添加读取权限 sudo chmod -R 755 /etc/letsencrypt/live /etc/letsencrypt/archive # 用ACL精细控制权限(可选) sudo setfacl -R -m u:101:rX /etc/letsencrypt/live /etc/letsencrypt/archive
3. 修复Nginx配置适配Angular单页应用
原配置的try_files会导致Angular路由刷新时404,修改nginx.conf:
http { server { listen 443 default_server ssl http2; listen [::]:443 ssl http2; server_name footeware.ca; ssl_certificate /etc/letsencrypt/live/footeware.ca/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/footeware.ca/privkey.pem; # 指定Angular静态文件根目录 root /usr/share/nginx/html/browser; index index.html; location / { # 单页应用路由 fallback 到index.html try_files $uri $uri/ /index.html; } } }
4. 验证证书可用性
在宿主机先确认软链接指向的真实文件存在:
sudo ls -l /etc/letsencrypt/live/footeware.ca/
正常输出应该类似:
lrwxrwxrwx 1 root root 41 Oct 20 16:37 fullchain.pem -> ../../archive/footeware.ca/fullchain1.pem lrwxrwxrwx 1 root root 39 Oct 20 16:37 privkey.pem -> ../../archive/footeware.ca/privkey1.pem
5. 测试容器启动
重新构建并启动容器:
docker-compose build docker-compose up --force-recreate
如果仍有问题,启动临时容器检查证书是否能被读取:
docker run -it --rm -v /etc/letsencrypt:/etc/letsencrypt nginx:latest bash # 在容器内执行以下命令验证 ls -l /etc/letsencrypt/live/footeware.ca/ cat /etc/letsencrypt/live/footeware.ca/fullchain.pem
补充:CertBot自动续期配置
因为你用的是standalone模式续期,需要确保续期时80端口未被占用(当前容器仅映射443,所以没问题)。如果后续容器需要用到80端口,可添加续期钩子脚本:
- 创建预续期脚本(停止容器):
sudo nano /etc/letsencrypt/renewal-hooks/pre/stop-nginx-container.sh
写入内容:
#!/bin/bash docker-compose -f /path/to/your/compose.yaml stop ng_web
- 创建续期后脚本(启动容器):
sudo nano /etc/letsencrypt/renewal-hooks/post/start-nginx-container.sh
写入内容:
#!/bin/bash docker-compose -f /path/to/your/compose.yaml start ng_web
- 给脚本添加执行权限:
sudo chmod +x /etc/letsencrypt/renewal-hooks/pre/stop-nginx-container.sh sudo chmod +x /etc/letsencrypt/renewal-hooks/post/start-nginx-container.sh
内容的提问来源于stack exchange,提问作者CraigFoote
相关产品推荐
相关产品推荐

