Nginx 反向代理 Docker 实现域名与 IP 的访问分流

1. 起因与冲突

最近在服务器上部署了两个东西:一个是基于 Hexo 的个人博客,另一个是基于 Docker 部署的 HOJ(Hcode Online Judge)

原本的想法很简单:

  • 输入域名 duziks.top 访问博客。
  • 输入服务器 IP 访问 OJ 系统。

遇到的坑: 两个服务都默认想要占用 80 端口。Docker 容器(hoj-frontend)先占了坑,导致 Nginx 启动时直接报错,提示端口被占用。


2. 解决思路:反向代理

核心思路是 “让出 80 端口,统一交给 Nginx 管理”

  1. 把 Docker 容器内部的 80 端口映射到宿主机的 8081 端口(避开公网默认的 80)。
  2. 让 Nginx 监听真正的 80 端口。
  3. Nginx 内部做判断:如果是域名访问,直接读静态文件;如果是 IP 访问,就把流量“转发”给内部的 8081 端口。

3. 操作实录

第一步:修改 Docker 端口映射

找到 HOJ 的安装目录(我的是在 ~/hoj-deploy/standAlone),修改 docker-compose.yml

hoj-frontendports 部分从 "80:80" 改为 "8081:80"

Bash

# 重启容器使配置生效
docker-compose up -d hoj-frontend

检查一下:执行 docker ps 看到 0.0.0.0:8081->80/tcp 就算成功了。

第二步:配置 Nginx 分流

/etc/nginx/conf.d/ 下配置 Nginx。关键在于准备两个 server 块。

1. 博客配置(匹配域名):

Nginx

server {
listen 80;
server_name duziks.top;
root /var/www/hexo;
index index.html;
# ... 其他配置
}

2. OJ 配置(兜底 IP 访问): 这里用到了 default_server,代表如果没匹配到域名,就全走这里。

Nginx

server {
listen 80 default_server;
server_name _;

location / {
proxy_pass http://127.0.0.1:8081; # 连接到 8081 的关键
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

第三步:重启与排错

执行 nginx -t 检查语法,没问题后重启 Nginx。

中间遇到的一个插曲: 刚改完访问 IP 出现了 502 Bad Gateway。 排查发现是 Docker 容器在重启过程中还没完全 Ready。等了一分钟,待 docker ps 状态稳定后,访问恢复正常。


4. 总结

通过这次折腾,搞清楚了几个关键点:

  • 80 端口是唯一的,多个服务共存必须通过 Nginx 这种代理服务器做分发。
  • 127.0.0.1:8081 成了 Nginx 和 Docker 之间的“悄悄话”通道,不需要在云服务器防火墙开启 8081,这样反而更安全。
  • 修改 docker-compose 之后,一定要确认容器状态是 Up 且端口映射正确。

现在的服务器终于清爽了:一个 80 端口,承载了两个完全不同的世界。