在 CentOS 服务器上通过 Docker Compose 配置多个 Nginx 容器并支持 HTTPS 的完整流程
本文介绍如何在一台 CentOS 服务器上使用 Docker Compose 部署多个 Nginx 容器服务,使用统一反向代理,并通过 Let’s Encrypt 免费证书配置 HTTPS,支持多个二级域名的访问。
一、准备工作
1. 系统环境
2. 文件结构建议
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| nginx-sites/ ├── blog-site/ │ ├── nginx.conf │ └── public/ ├── work-site/ │ ├── nginx.conf │ └── html/ ├── data/ │ ├── certbot/ │ │ ├── www/ │ │ └── conf/ │ └── nginx/ │ └── conf.d/ ├── docker-compose.yml
|
二、编写 docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| version: '3' services: nginx-blog-site: image: nginx:latest container_name: nginx-blog-site volumes: - ./blog-site/nginx.conf:/etc/nginx/conf.d/default.conf - ./blog-site/public:/usr/share/nginx/html networks: - nginx-net
nginx-work-site: image: nginx:latest container_name: nginx-work-site volumes: - ./work-site/nginx.conf:/etc/nginx/conf.d/default.conf - ./work-site/html:/usr/share/nginx/html networks: - nginx-net
reverse-proxy: image: nginx:latest container_name: nginx-proxy ports: - "80:80" - "443:443" volumes: - ./data/nginx/conf.d:/etc/nginx/conf.d - ./data/certbot/www:/var/www/certbot - ./data/certbot/conf:/etc/letsencrypt depends_on: - nginx-blog-site - nginx-work-site networks: - nginx-net
certbot: image: certbot/certbot container_name: certbot volumes: - ./data/certbot/www:/var/www/certbot - ./data/certbot/conf:/etc/letsencrypt networks: - nginx-net command: > certonly --webroot --webroot-path=/var/www/certbot \ --agree-tos --no-eff-email --email [email protected] \ -d blog.example.com -d work.example.com
networks: nginx-net: driver: bridge
|
三、反向代理 Nginx 配置(HTTPS)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
server { listen 80; server_name blog.example.com work.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$host$request_uri; } }
server { listen 443 ssl; server_name blog.example.com;
ssl_certificate /etc/letsencrypt/live/blog.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/blog.example.com/privkey.pem;
location / { proxy_pass http://nginx-blog-site:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
server { listen 443 ssl; server_name work.example.com;
ssl_certificate /etc/letsencrypt/live/blog.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/blog.example.com/privkey.pem;
location / { proxy_pass http://nginx-work-site:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
|
说明:虽然证书文件路径以 blog.example.com 命名,但它实际是通用证书,包含多个域名(SAN 证书)。
四、启动流程
步骤 1:启动 Nginx 服务和反向代理
1
| docker-compose up -d nginx-blog-site nginx-work-site reverse-proxy
|
❌ reverse-proxy 容器启动失败,提示找不到证书?
证书申请前,reverse-proxy.conf配置文件中先不要配置 HTTPS,使用如下临时配置:
1 2 3 4 5 6 7 8 9 10 11
| server { listen 80; server_name blog.example.com work.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$host$request_uri; } }
|
步骤 2:申请 HTTPS 证书
✅ 前提准备
- 确保 DNS 已解析到服务器 IP。
- 若使用 Cloudflare 并启用了“代理(橙色云朵)”,必须先关闭代理功能(即灰色云朵,暴露真实 IP),否则验证失败。
- 先运行
reverse-proxy 容器,确保 80 端口可访问。
1 2
| docker-compose up -d reverse-proxy
|
📥 申请证书
1 2 3 4 5 6 7 8
| docker-compose run --rm certbot
docker-compose run --rm certbot certonly \ --webroot --webroot-path=/var/www/certbot \ --agree-tos --no-eff-email --email 你的邮箱 \ -d blog.example.cn -d work.example.cn
|
成功后,会看到提示:
1 2
| Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/blog.example.com/fullchain.pem
|
你可以验证证书内容:
1
| openssl x509 -in ./data/certbot/conf/live/blog.example.com/fullchain.pem -noout -text | grep DNS:
|
📌 提示:多个子域名的证书会保存在同一个主目录中
比如同时申请 blog.example.cn 和 work.example.cn,证书统一保存在:
1
| /etc/letsencrypt/live/blog.example.cn/
|
步骤 3:恢复reverse-proxy.conf中HTTPS相关配置,重新加载或重启 reverse-proxy 服务
1
| docker-compose restart reverse-proxy
|
五、证书续期(推荐自动化)
手动续期测试:
1
| docker-compose run --rm certbot renew --dry-run
|
自动续期方案(推荐 crontab)
1
| 0 3 * * * docker-compose run --rm certbot renew && docker-compose exec reverse-proxy nginx -s reload
|
六、注意事项
❌ 证书申请失败,报错 521 或 connection refused?
- 检查 Cloudflare 是否启用了代理,必须关闭。
- 检查 80 端口是否在安全组中放行。
- 使用以下命令验证:
1
| curl http://yourdomain/.well-known/acme-challenge/test.txt
|
❌ nginx 启动失败,提示找不到证书?
证书申请前,先不要配置 HTTPS,使用如下临时配置:
1 2 3 4 5 6 7 8 9 10
| server { listen 80; server_name yourdomain; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 200 'Nginx HTTP ok'; } }
|
证书申请成功后再切换为 HTTPS 配置。
❌使用CDN代理后,出现 ERR_TOO_MANY_REDIRECTS 问题,重定向次数过多!
使用 Cloudflare 代理(橙色云)时,Cloudflare 作为中间层会以不同 SSL 模式请求源站(你的服务器),如果设置不当,会造成“HTTP↔HTTPS”的重定向死循环!
将 Cloudflare 的 SSL 模式设置为 Full
- 登录 Cloudflare 控制台
- 进入你的域名 → SSL/TLS → Overview
- 将 SSL 模式设置为 Full(或 Full (strict),如果你用的是有效的 Let’s Encrypt 证书)
👉 这个设置表示 Cloudflare 用 HTTPS 请求你的服务器,就不会因为 HTTP 到 HTTPS 重定向而死循环了。
七、总结
通过本文步骤,你可以在一台 CentOS 服务器上:
- 部署多个站点容器服务
- 使用统一反向代理暴露端口
- 成功为多个域名配置 HTTPS 访问
- 实现 Docker 化部署 + Let’s Encrypt 免费证书自动化管理
- 多个子域名可以共用一个证书,只需一次申请。
- 使用 webroot 模式部署简单,但注意 DNS 和代理配置。
- 使用 Docker Compose + 反向代理架构,灵活、隔离、易维护。
- 后期可切换到 DNS 验证(dns-01 challenge),适合自动化和内网服务。