用 Nginx 给多个 Docker 服务做反向代理与 HTTPS 统一收口
随着本机跑的 Docker 服务越来越多——代码托管、笔记同步、监控面板……每个服务都暴露一个端口,时间久了根本记不住哪个端口对应哪个服务。更头疼的是,如果想从公网访问,裸端口+自签证书的体验实在太差。这次索性用 Nginx 做了一个统一的反向代理入口,顺手把 HTTPS 也一起配好。
整体思路是:Nginx 容器监听宿主机的 80 和 443 端口,根据请求的域名(或子域名)把流量转发到对应的内部 Docker 服务。证书用 Let's Encrypt 的 Certbot 申请,通过挂载数据卷的方式让 Nginx 读取。这样对外只暴露两个端口,内部服务全部缩在 Docker 网络里,安全性也好了不少。
关键配置片段
在 nginx.conf 里,每个服务对应一个 server 块。以代码托管服务为例:
server {
listen 443 ssl;
server_name git.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://gitea:3000;
proxy_set_header Host $host;
}
}
listen 443 ssl;
server_name git.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://gitea:3000;
proxy_set_header Host $host;
}
}
这里 proxy_pass 里直接写 Docker 服务名 gitea,因为 Nginx 容器和它在同一个 Docker 网络里,DNS 自动解析,不需要写 IP。这个细节一开始没注意,还傻乎乎地去查容器 IP,踩了一个不小的坑。
证书自动续期
Let's Encrypt 证书有效期只有 90 天,手动续期迟早会忘。用 cron 每两个月跑一次 certbot renew,续期后再执行 docker exec nginx nginx -s reload 重载配置,全程不需要人工干预,基本可以一劳永逸。
配好之后,所有服务都通过子域名访问,浏览器地址栏那把绿色小锁看着也顺眼多了。