简而言之
你需要三个东西才能使它工作:
- 预定义的外部网络,以通过固定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协议,在本地监听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:
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
作为网络,以及针对网络bridged
的aliases
条目,其中还涉及其他服务。
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
docker-compose.yml
文件吗? - Pierre B.