Docker+Nginx环境下Certbot自动续期SSL证书配置问题
问题分析与解决方案
核心问题
你的配置存在三个关键问题,导致Certbot自动续期时验证失败:
验证模式与Nginx端口冲突
错误提示使用了standalone验证模式,但你的Nginx已经占用443端口(且未配置80端口服务),Certbot无法启动独立的验证服务器处理ACME挑战,导致验证请求返回404。Nginx配置缺失与路径错误
- 缺少80端口server块:ACME挑战默认通过HTTP(80端口)发起,仅配置HTTPS服务无法接收初始验证请求。
/.well-known/acme-challenge/的root路径错误:你指定的/etc/letsencrypt不是Certbot存放验证文件的默认路径,即使请求被Nginx拦截,也找不到对应文件。
Docker Compose配置不完整
- Certbot容器未与Nginx共享webroot目录,无法通过webroot模式传递验证文件。
certbot renew未指定验证方式,默认沿用之前的standalone模式,加剧端口冲突。
解决方案(推荐Webroot模式,无需中断Nginx服务)
1. 修正Nginx配置
添加80端口server块,处理ACME挑战并将HTTP请求重定向到HTTPS:
# 新增80端口server块 server { listen 80; listen [::]:80; server_name example.com; # 处理ACME验证请求 location ^~ /.well-known/acme-challenge/ { allow all; root /var/www/html; # 共享目录,用于存放验证文件 } # 其他HTTP请求重定向到HTTPS location / { return 301 https://$host$request_uri; } } # 保留原443端口配置,可删除其中的acme-challenge location(已由80端口处理) server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; auth_basic_user_file .htpasswd; # SSL配置 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_session_cache shared:le_nginx_SSL:10m; ssl_session_timeout 1440m; ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; client_max_body_size 4G; keepalive_timeout 5; }
2. 完善Docker Compose配置
确保Nginx与Certbot共享webroot目录,并指定webroot验证模式:
services: nginx: image: nginx:alpine restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf # 替换为你的Nginx配置文件路径 - /etc/letsencrypt:/etc/letsencrypt - /var/www/html:/var/www/html # 共享webroot目录 certbot: image: certbot/certbot restart: unless-stopped volumes: - /etc/letsencrypt:/etc/letsencrypt - /var/www/html:/var/www/html # 共享webroot目录 entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --webroot -w /var/www/html; sleep 12h & wait $${!}; done;'" volumes: database: app:
3. 启动服务
在宿主机创建共享目录,然后重启容器:
mkdir -p /var/www/html docker-compose down && docker-compose up -d
备选方案(Standalone模式,需临时停止Nginx)
如果坚持使用standalone模式,需修改Certbot的entrypoint命令,临时停止Nginx完成验证后再启动:
certbot: image: certbot/certbot restart: unless-stopped volumes: - /etc/letsencrypt:/etc/letsencrypt - /var/run/docker.sock:/var/run/docker.sock # 允许容器操作宿主机Docker entrypoint: "/bin/sh -c 'trap exit TERM; while :; do docker stop nginx; certbot renew; docker start nginx; sleep 12h & wait $${!}; done;'"
此方式会短暂中断Nginx服务,不推荐用于生产环境。
内容的提问来源于stack exchange,提问作者popcorn
相关产品推荐
相关产品推荐

