如何在 Docker 容器中配置 Nginx 反向代理宿主机服务?

文章导读
在 Docker 容器里让 Nginx 反代宿主机,最稳妥的方式是通过 host.docker.internal 配合网关参数,或者直接指定宿主机局域网 IP,避免直接用 localhost。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
A A

在 Docker 容器里让 Nginx 反代宿主机,最稳妥的方式是通过 host.docker.internal 配合网关参数,或者直接指定宿主机局域网 IP,避免直接用 localhost。

先说结论:Linux 下需显式添加 host 映射,macOS/Windows 默认支持,生产环境建议固定 IP 或网关方式。

  • 适合 Docker 20.10+ 或已知宿主机 IP 的场景
  • 先准备 Nginx 配置文件和 Docker 启动参数
  • 验收容器内 curl 宿主机端口是否通

命令速用版

docker run -d `--name` nginx-proxy \
  `--add-host`=host.docker.internal:host-gateway \
  -p 80:80 \
  -v /path/to/nginx.conf:/etc/nginx/nginx.conf \
  nginx:latest

Nginx 完整配置示例(nginx.conf):

events {
    worker_connections 1024;
}

http {
    server {
        listen 80;
        location / {
            proxy_pass http://host.docker.internal:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

为什么会这样

Docker 容器默认运行在独立的网络命名空间中。容器内的 localhost127.0.0.1 指向的是容器自己,而不是宿主机。如果要访问宿主机上运行的服务(比如宿主机本地的 8080 端口),必须找到宿主机在 Docker 网络中的可达地址。

在 macOS 和 Windows 上,Docker Desktop 默认配置了 host.docker.internal 域名指向宿主机。但在 Linux 上,这个功能不是默认开启的,需要 Docker 20.10 及以上版本,并在启动时通过 `--add-host` 参数手动注入,或者直接使用宿主机在 Docker 网桥上的网关 IP(通常是 172.17.0.1)。

分步处理

1. 确认宿主机可达地址

如果你使用的是 Docker 20.10 及以上版本,推荐使用 host.docker.internal。如果是旧版本,或者想更稳妥,可以查看默认网桥的网关 IP:

ip addr show docker0 | grep "inet "

通常你会看到类似 172.17.0.1 的地址,这就是容器访问宿主机的入口。

2. 编写 Nginx 配置

如何在 Docker 容器中配置 Nginx 反向代理宿主机服务?

在宿主机上创建 nginx.conf,将 proxy_pass 指向刚才确认的地址。如果使用 host.docker.internal,配置如上所示;如果使用 IP,则改为 http://172.17.0.1:8080。注意配置需包含 events 和 http 块才能作为主配置文件运行。

3. 启动容器并注入 Host

如果使用域名方式,必须在 docker run 时加上 `--add-host`=host.docker.internal:host-gateway。这一步是关键,否则容器内无法解析该域名。

4. 检查宿主机防火墙

确保宿主机防火墙允许来自 Docker 网桥网段的连接。例如在 firewalld 中,可能需要放行特定端口或信任 docker 区域。

怎么验证是否生效

进入容器内部发起请求,看是否能拿到宿主机服务的响应:

docker exec -it nginx-proxy curl -v http://host.docker.internal:8080

如果返回 HTTP 200 且内容正确,说明反向代理链路已通。如果连接被拒绝(Connection refused),通常是宿主机服务没监听 0.0.0.0,或者防火墙拦截了。

如何在 Docker 容器中配置 Nginx 反向代理宿主机服务?

常见坑

1. 宿主机服务监听地址

很多服务默认只监听 127.0.0.1。在容器里访问时,流量是从网卡进来的,宿主机服务必须监听 0.0.0.0 才能接收来自容器的请求。

2. IP 地址变动

如果使用硬编码的 IP(如 172.17.0.1),当 Docker 服务重启或网络配置变更时,网关 IP 可能会变。使用 host-gateway 参数相对更稳定,但仍需注意 Docker 版本兼容性。

3. 网络模式混淆

如果容器使用了 network_mode: "host",则容器共享宿主机网络,可以直接用 localhost。但这会失去网络隔离,端口也容易冲突,一般不建议为了反代宿主机而改用 host 模式。

4. SELinux 限制

在 CentOS/RHEL 等开启 SELinux 的系统上,容器可能无法访问宿主机某些端口或文件。如果排查无误仍不通,可尝试临时设置 setenforce 0 测试(注意:生产环境请勿永久关闭,建议配置正确 SELinux 策略)。