为了解决工作项目中一些操作上的愚蠢问题,我正在尝试:
- 运行服务 A 监听
localhost:4001
并运行服务 B 监听localhost:4002
。 - 在 Docker 容器内运行 Nginx;内部监听
0.0.0.0:80
- 在主机系统上设置 Docker 监听 localhost:80,将请求转发到 Nginx 容器中的端口 80。
- 设置 Nginx 转发
localhost:80/a
到localhost:4001
,并转发localhost:80/b
到localhost:4002
。
我可以编写自己的nginx.conf
文件,但出于操作和组织的原因,我只能在 Docker 内运行 Nginx。
但是,是否可以让运行在容器内的 Nginx 服务器将请求代理到环回设备主机系统?
我正在尝试做的事情的图表:
┌──────────────────┐
│ │
│ My web browser │─┐
└──────────────────┘ │
│
┌────────────────────────────────┼───────┐
│ │ │
│ ┌──────────────────────┐ │ │
│ │ │← │ │
┌───┼──────│ Nginx (0.0.0.0:80) │──┘ │
│ ┌─┼──────│ │ │
│ │ │ └──────────────────────┘ │
│ │ │ │
│ │ │ Docker (localhost:80 -> 172.17.0.1:80) │
│ │ └────────────────────────────────────────┘
│ └────────────────────────────┐
│ │
↓│ ↓│
┌───────────────────────────┐ ┌───────────────────────────┐
│ │ │ │
│ Daemon A (localhost:4001) │ │ Daemon B (localhost:4002) │
└───────────────────────────┘ └───────────────────────────┘
答案1
根据设计,监听 或 的应用程序localhost
只能127.0.0.1/8
在::1/128
同一台机器上本地访问。或者严格地说,从同一个网络命名空间访问。默认情况下,Docker 容器有自己的网络命名空间,它附带另一个单独的 实例localhost
。
因此,使用默认的 Docker 网络,您想要的功能是不可能的:容器无法连接到主机的localhost
。
Docker还支持一种特殊的网络模式:主机网络。如果在启动容器时指定此项,则不会将其放入单独的网络命名空间,而是使用主机网络命名空间。主机和容器的网络命名空间localhost
将相同。但是,有以下影响:
- 端口映射无效
- 您需要注意不要重复使用端口
- 主机网络不能与链接混合
根据您的设置,nginx 失去对其他容器的访问权限是不可接受的。
您也可以使用类似的方法socat
来让 Docker 容器可以访问该端口:
docker run -d --restart=always --network=host alpine/socat TCP4-LISTEN:4001,fork,reuseaddr,interface=docker0 TCP4-CONNECT:localhost:4001
从你的 nginx 容器,你可以使用默认网络访问 172.17.0.1 处的主机。
您还可以尝试添加--add-host=host.docker.internal:host-gateway
到 nginx 容器调用中以获取 DNS 名称 ( host.docker.internal
),无论配置如何,该名称始终有效。这仅适用于最新版本的 Docker。