tl;博士
你需要做 3 件事才能让它发挥作用:
- 预定义的外部网络,用于通过固定 IP 访问主机
-
hostname 每个参与服务的条目
- 作为路由器的附加 Docker 服务,用于将请求重定向到主机。我们还将使用
aliases 条目来允许其他服务通过预定义的主机名访问此路由器服务。
如何
注意:已针对 Linux 测试。不确定,它是否适用于 Windows。
- 使用网关创建外部网络。例如。通过下面定义的自定义 IP
172.30.0.1,每个 docker 服务应该能够访问主机。
docker network create \
--driver=bridge \
--subnet=172.30.0.0/16 \
--gateway=172.30.0.1 \
host-net
- 为您的 docker-compose.yml 中的每个参与服务添加自定义
hostname,例如
services:
service-1:
hostname: service-1.in.docker
service-2:
hostname: service-2.in.docker
所以,service-2 现在可以通过域 service-1.in.docker 访问service-1,反之亦然。
- 创建一个附加服务,利用众所周知的多用途中继工具socat 来充当路由器,例如
services:
router:
image: alpine/socat
command: TCP-LISTEN:5900,fork TCP:172.30.0.1:15900
这里基于 TCP,它在 localhost 的 5900 端口上侦听,并将传入的请求重定向到目标 172.30.0.1(网关 -> 主机)的 15900 端口。
示例
version: "3.9"
services:
router:
image: alpine/socat
entrypoint: >
sh -c "
socat TCP-LISTEN:5900,fork TCP:172.30.0.1:15900 &
socat TCP-LISTEN:5901,fork TCP:172.30.0.1:15901 &
wait
"
networks:
host-net:
bridged:
aliases:
- service-1.in.docker
service-1:
# hostname: service-1.in.docker
image: hashicorp/http-echo
command: -listen=:5900 -text="hello world"
networks:
bridged:
service-2:
hostname: service-2.in.docker
image: curlimages/curl:7.75.0
command: ["sh", "-c", "while true; do curl service-1.in.docker:5900 && sleep 5; done"]
networks:
bridged:
networks:
host-net:
external: true
bridged:
注意事项:
-
这里的router服务包括两个重要的东西:host-net作为网络,aliases网络入口bridged,其中还涉及其他服务。
-
router 服务的工作原理如下:
(请求)-> [localhost:5900] ->(重定向)-> [172.30.0.1:15900]
(请求)-> [localhost:5901] ->(重定向)-> [172.30.0.1:15901]
-
由于我们注释了hostname: service-1.in.docker 行,service-2 (curl service-1.in.docker:5900) 发出的 curl 请求将转到 router 服务(由于别名 service-1.in.docker)。随后,这些请求被转发到 15901 端口上的主机。
-
如果我们注释掉 hostname: service-1.in.docker 行,service-1 会以“hello world”回复service2。
如果您可以动态更改各个服务使用的主机名,例如环境变量或属性文件等,则可以使用它们,因此您不必每次都注释掉:
services:
router:
image: alpine/socat
networks:
bridged:
aliases:
- service-1.in.router
service-2:
hostname: service-2.in.docker
command: ["sh", '-c', 'while true; do curl ${DEST_SERVICE_HOST_ADDR_SET_BY_ENV_VAR} && sleep 5; done']
DEST_SERVICE_HOST_ADDR_SET_BY_ENV_VAR可根据需要提供service-1.in.router或service-1.in.docker。
脚注:
你可以在你的主机上运行一个测试服务器来测试这个,例如:
python3 -m http.server 15901