🌐 阿里云 Linux 服务器 + Docker 中运行 Nginx 的 Let's Encrypt 多网站 SSL 证书部署指南
适用系统:Alibaba Cloud Linux 3(兼容 CentOS/RHEL)
Web 服务器:Nginx(运行在 Docker 容器中)
场景:托管 多个独立网站(如site1.com、site2.net等)
更新时间:2025 年 11 月
作者:DevOps Guide
✅ 一、核心原则
- 每个独立网站使用独立的 Let's Encrypt 证书
- Certbot 在宿主机运行(不放入容器)
- 证书通过 Volume 挂载到 Nginx 容器
- 使用
webroot验证方式(无需停机) - 自动续期 + 自动重载 Nginx
🚀 二、前提条件
| 要求 | 说明 |
|---|---|
| 1. 阿里云 ECS 实例 | 操作系统为 Alibaba Cloud Linux 3 |
| 2. 多个域名已解析 | 各域名 A 记录均指向 ECS 公网 IP |
| 3. 安全组开放 80/443 | 入站规则允许 0.0.0.0/0 访问 80 和 443 |
| 4. 域名已备案(如适用) | 中国内地地域必须完成 ICP 备案 |
| 5. Docker 已安装 | 且能正常运行容器 |
📦 三、目录结构规划(宿主机)
/home/user/my-websites/
├── docker-compose.yml
├── nginx.conf
├── site1/ # 网站1 静态文件
├── site2/ # 网站2 静态文件
└── /var/www/letsencrypt # ← 全局 ACME 验证目录(由 Certbot 写入)
💡
/etc/letsencrypt由 Certbot 自动管理,无需手动创建
🔧 四、完整操作流程
步骤 1:创建 ACME 验证目录(宿主机)
sudo mkdir -p /var/www/letsencrypt
sudo chmod 755 /var/www/letsencrypt
此目录将用于所有网站的 HTTP-01 挑战验证
步骤 2:编写 docker-compose.yml
# docker-compose.yml
version: '3'
services:
nginx:
image: nginx:alpine
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
# ACME 验证目录(只读)
- /var/www/letsencrypt:/var/www/letsencrypt:ro
# Let's Encrypt 证书目录(只读)
- /etc/letsencrypt:/etc/letsencrypt:ro
# 各网站根目录
- ./site1:/var/www/site1:ro
- ./site2:/var/www/site2:ro
# Nginx 主配置
- ./nginx.conf:/etc/nginx/nginx.conf:ro
restart: unless-stopped
步骤 3:编写 Nginx 配置 nginx.conf
# nginx.conf
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# === 网站 1:site1.com ===
server {
listen 80;
server_name site1.com www.site1.com;
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name site1.com www.site1.com;
ssl_certificate /etc/letsencrypt/live/site1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/site1.com/privkey.pem;
root /var/www/site1;
index index.html;
try_files $uri $uri/ =404;
}
# === 网站 2:site2.net ===
server {
listen 80;
server_name site2.net app.site2.net;
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name site2.net app.site2.net;
ssl_certificate /etc/letsencrypt/live/site2.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/site2.net/privkey.pem;
root /var/www/site2;
index index.html;
try_files $uri $uri/ =404;
}
}
✅ 每个网站独立
server块,独立证书路径
步骤 4:启动 Nginx 容器
# 启动前确保配置正确
sudo nginx -t -c ./nginx.conf
# 启动容器
docker-compose up -d
✅ 此时应能通过
http://site1.com和http://site2.net访问(会重定向到 HTTPS,但证书还未部署)
步骤 5:安装 Certbot(宿主机)
sudo dnf install -y epel-release
sudo dnf install -y certbot
步骤 6:为每个网站申请证书(宿主机)
# 网站1
sudo certbot certonly --webroot -w /var/www/letsencrypt -d site1.com -d www.site1.com
# 网站2
sudo certbot certonly --webroot -w /var/www/letsencrypt -d site2.net -d app.site2.net
✅ 证书将分别存放在:
/etc/letsencrypt/live/site1.com//etc/letsencrypt/live/site2.net/
步骤 7:验证证书
sudo certbot certificates
输出应类似:
Certificate Name: site1.com
Domains: site1.com www.site1.com
Expiry Date: 2026-02-20 ...
Certificate Name: site2.net
Domains: site2.net app.site2.net
Expiry Date: 2026-02-22 ...
步骤 8:测试 HTTPS 访问
浏览器访问:
https://site1.com→ 应显示安全锁https://site2.net→ 应显示安全锁
步骤 9:配置自动续期(关键!)
9.1 测试续期(不会真续)
sudo certbot renew --dry-run
✅ 应看到:All simulated renewals succeeded.
9.2 添加定时任务
sudo crontab -e
粘贴:
0 2 * * * /usr/bin/certbot renew --quiet --post-hook "docker exec nginx nginx -s reload"
9.3 验证
sudo crontab -l
✅
--post-hook会在任一证书续期成功后自动重载 Nginx,加载新证书
🔍 五、常见问题排查
❌ 问题 1:404 访问 /.well-known/acme-challenge/xxx
原因:Nginx 未正确路由 ACME 路径
解决:
- 确保每个
server { listen 80; }块包含:location /.well-known/acme-challenge/ { root /var/www/letsencrypt; } - 确认容器挂载了
/var/www/letsencrypt
❌ 问题 2:Permission denied 读取证书
原因:容器内 Nginx 无权读取 /etc/letsencrypt
解决:
- 挂载时使用
:ro(只读)通常足够 - 若仍报错,可复制证书到项目目录并调整权限:
并修改sudo cp -r /etc/letsencrypt ./certs sudo chown -R $USER:$USER ./certsdocker-compose.yml挂载./certs:/certs
❌ 问题 3:续期后 HTTPS 仍用旧证书
原因:未触发 nginx -s reload
解决:
- 检查 cron 中的
--post-hook是否正确 - 手动测试:
docker exec nginx nginx -s reload
📎 六、扩展场景
🌐 通配符证书(*.example.com)
需使用 DNS 验证(阿里云 DNS):
sudo dnf install -y certbot-dns-alidns
# 创建凭证文件 ~/.secrets/alidns.ini
dns_alidns_access_key = YOUR_KEY
dns_alidns_secret_key = YOUR_SECRET
chmod 600 ~/.secrets/alidns.ini
# 申请通配符证书
sudo certbot certonly \
--dns-alidns \
--dns-alidns-credentials ~/.secrets/alidns.ini \
-d '*.example.com' -d example.com
⚠️ 通配符证书不能覆盖多级子域(如
a.b.example.com)
✅ 七、总结:多网站最佳实践
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 创建统一 ACME 目录 | /var/www/letsencrypt |
| 2 | 编写多 server Nginx 配置 | 每个网站独立块 |
| 3 | 为每个主域名申请证书 | 使用 certbot certonly --webroot |
| 4 | 挂载 /etc/letsencrypt 到容器 | 只读即可 |
| 5 | 设置自动续期 cron | 含 --post-hook "nginx -s reload" |
🎉 完成!多个网站均拥有自动更新的免费 HTTPS
🔗 官方参考:
💡 提示:每季度运行
sudo certbot certificates检查到期时间,确保万无一失。