通过 Docker配置多个 Nginx 容器并支持 HTTPS

在 CentOS 服务器上通过 Docker Compose 配置多个 Nginx 容器并支持 HTTPS 的完整流程

本文介绍如何在一台 CentOS 服务器上使用 Docker Compose 部署多个 Nginx 容器服务,使用统一反向代理,并通过 Let’s Encrypt 免费证书配置 HTTPS,支持多个二级域名的访问。


一、准备工作

1. 系统环境

  • 操作系统:CentOS 7+/8+

  • Docker 已安装

  • Docker Compose 已安装

  • 已有可用的二级域名(如 blog.example.comwork.example.com),并配置正确的 DNS 解析到服务器公网 IP

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/ # Certbot webroot
│ │ └── 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
# ./data/nginx/conf.d/reverse-proxy.conf

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
# 启动 reverse-proxy 提供 HTTP 验证入口
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.cnwork.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

六、注意事项

  • 你的 DNS 必须正确指向服务器公网 IP。

  • 防火墙需开放 80 和 443 端口。

  • Nginx proxy_pass 的容器名称必须与 docker-compose 中定义的一致。

  • 多个域名使用同一个 SAN 证书是常规做法。

❌ 证书申请失败,报错 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

  1. 登录 Cloudflare 控制台
  2. 进入你的域名 → SSL/TLSOverview
  3. 将 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),适合自动化和内网服务。

通过 Docker配置多个 Nginx 容器并支持 HTTPS
http://eevann.cn/2025/06/17/docker-nginx-https/
作者
月下独白
发布于
2025年6月18日
许可协议