这是「把自己部署到互联网上」系列的第 24 篇。
上一篇我确定了 Nginx 方案:
- 用一个全局
Nginx统一管理多个项目的公网入口 - 公网只进入 80 和 443,Nginx 根据域名把请求转发到不同项目
- 每个项目内部仍然用
Docker Compose管理应用、数据库和数据卷 - 数据库不暴露公网
- 证书集中管理
- 新增项目按统一规则接入
这一篇开始落到操作层面。目标是先把全局 Nginx 容器跑起来,确认它具备接入多个项目的基础能力:能占用 80 和 443,配置文件在宿主机可维护,加入公共 Docker 网络,日志能查看,配置能检查,也能安全 reload。
开始前,-服务器已经完成基础准备:
- 可以用普通用户登录
Docker和 Docker Compose 可用- 云平台安全组和系统防火墙已放行 80、443,且当前没有其他服务占用这两个端口。
可以先检查服务器端口:
sudo ss -lntp | grep -E ':80|:443'
如果系统 Nginx、Apache、Caddy 或其他服务已经占用 80/443,会导致全局 Nginx 容器就绑定。我的服务器是新买的,所以说不太可能出现这种情况,如果已有服务占用了,就要考虑下把占用服务停掉,重新分配端口。
准备目录
我会把全局 Nginx 的配置、证书和日志放到固定位置,例如:
/opt/coduty/nginx/
docker-compose.yml
conf.d/
certs/
logs/
创建目录:
sudo mkdir -p /opt/coduty/nginx/conf.d
sudo mkdir -p /opt/coduty/nginx/certs
sudo mkdir -p /opt/coduty/nginx/logs
如果日常维护用户是 coduty,顺便调整操作权限:
sudo chown -R coduty:coduty /opt/coduty
存放路径自由发挥,不一定必须叫 /opt/coduty,
关键是结构清楚:
Nginx有独立目录,配置放conf.d,证书放certs,日志放logs,Compose 文件放在入口目录下。
以后迁移服务器时,这套目录就是入口配置的主要资产。
创建公共 Docker 网络
全局 Nginx 容器要代理到不同项目容器,就必须和这些容器网络互通。
先创建一个外部公共网络:
docker network create coduty-public # 网络名可以按照自己的习惯命名
如果网络已经存在,就不需要重复创建。可以查看:
docker network ls
为什么要公共网络?
因为每个 Compose 项目默认有自己的内部网络。博客有博客的网络,官网有官网的网络。
全局 Nginx 如果不加入对应网络,就不能直接通过服务名访问项目容器。
我的设计是:
- 项目保留自己的默认内部网络
- 只有需要被全局
Nginx代理的应用容器,额外加入coduty-public - 数据库容器通常不加入公共网络,只给项目内部应用访问
编写全局 Nginx 的 Compose 文件。
进入刚才创建好的目录:
cd /opt/coduty/nginx
创建 docker-compose.yml:
services:
nginx:
image: nginx:alpine
container_name: global-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs:ro
- ./logs:/var/log/nginx
networks:
- coduty-public
networks:
coduty-public:
external: true # 这个是关键,其他要通信的容器,也必须要有这一行
这里的重点参数解释下:
container_name固定容器名,方便后续执行docker exec global-nginx nginx -trestart: unless-stopped让容器在异常退出或服务器重启后自动拉起ports只映射 80 和 443conf.d和certs以只读方式挂载,避免容器内误改logs挂载到宿主机,方便查看和备份coduty-public是前面创建的外部网络。
准备最小配置。
创建 /opt/coduty/nginx/conf.d/default.conf:
server {
listen 80;
server_name _;
location / {
return 200 "global nginx is running\n";
}
}
这个配置暂时不代理项目,也不处理 HTTPS,只用于验证全局入口是否正常。先用最小配置确认 Nginx 能启动、80 端口能访问、安全组和防火墙都没问题,再逐步接入项目。
启动容器。
在 /opt/coduty/nginx 下执行:
docker compose up -d
docker ps
docker logs global-nginx
如果启动失败,按顺序查:80/443 是否被占用,coduty-public 网络是否存在,挂载目录是否存在,配置文件是否有语法错误。容器没起来时,docker exec 用不了,可以先看:
docker compose logs
检查配置并 reload
全局 Nginx 是入口服务,每次改配置都要先执行检查:
docker exec global-nginx nginx -t
通过后再重载:
docker exec global-nginx nginx -s reload
千万不要跳过 nginx -t。后面博客、官网、作品站都接入后,一个错误配置可能影响多个站点。
自己的业务还好,再改下就好,公司的业务,还是建议慎重一些。
访问验证
如果服务器 IP 是 1.2.3.4,可以访问:
http://1.2.3.4
或执行:
curl http://1.2.3.4
预期返回:
global nginx is running
如果访问不到,按链路排查:容器是否运行;Nginx 是否监听 80;安全组是否放行;系统防火墙是否放行;本机是否能 curl http://127.0.0.1。如果本机能访问、外部不能访问,问题大概率在安全组、防火墙或公网链路;如果本机也不能访问,重点查容器、端口绑定和 Nginx 配置。
后续接入项目
博客应用容器叫 blog-app,监听 8000 端口,并加入了 coduty-public 网络,Nginx 配置可以写成:
server {
listen 80;
server_name blog.example.com;
location / {
proxy_pass http://blog-app:8000; # 这里就是通过 容器名 进行通信
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
这里的关键是 blog-app 必须能被 Nginx 容器解析到。也就是说,Nginx 和博客应用必须在同一个 Docker 网络里,并且服务名、容器名或网络别名要匹配。
可以进入 Nginx 容器测试:
docker exec -it global-nginx sh
wget -qO- http://blog-app:8000
如果失败,检查项目容器是否运行、是否加入公共网络、名称是否写对、应用是否监听正确端口。还要注意:如果应用只监听容器内的 127.0.0.1,其他容器可能访问不到,通常应监听 0.0.0.0 的服务端口。
配置文件
配置文件也要拆分。不要把所有站点写进一个巨大文件。推荐一个应用一个文件:
conf.d/
default.conf
blog.aicultiv.com.conf
www.aicultiv.com.conf
api.aicultiv.com.conf
新增项目加一个文件,删除项目也能明确清理。后面 HTTPS 的 80 跳转和 443 证书配置,也可以放在对应站点文件里。
日志
日志方面,因为挂载到了宿主机 /opt/coduty/nginx/logs,可以直接查看:
ls -lh /opt/coduty/nginx/logs
docker logs global-nginx
后面可以按站点拆日志:
access_log /var/log/nginx/blog.access.log;
error_log /var/log/nginx/blog.error.log;
这样博客和官网的问题能分开排查。
常见问题
常见问题也很明确。
- 端口被占用时,先用
ss查谁占用了 80/443,不要随便改端口逃避 Nginx找不到项目容器时,用docker network inspect coduty-public看两个容器是否在同一网络- 配置改了没生效时,先
nginx -t,再reload,并检查挂载路径是否正确 - 外部访问不到时,按 DNS、安全组、防火墙、Nginx 容器、端口监听、域名匹配、项目服务、Nginx 日志逐层查
到这里,全局 Nginx 还缺少HTTPS,也没有真正代理博客项目,但已经具备统一入口的基础:
目录清楚,公共网络存在,容器能启动,配置能检查,日志能查看,后续项目可以按固定方式接入
下一篇做阶段性复盘:从 Conda 到 Docker,再到全局 Nginx,我终于理清了部署架构。
本文由 楸木 原创,转载请注明出处。