[英]Redirect host inside docker-compose network to localhost outside docker
I have a set of containers I run using docker-compose.我有一组使用 docker-compose 运行的容器。 The network is the default network docker-compose creates, and the containers talk to each other using the hostnames docker-compose sets up automatically.该网络是 docker-compose 创建的默认网络,容器使用 docker-compose 自动设置的主机名相互通信。 So if I define a service named "my_service" in docker-compose, I access this container as the host "my_service".因此,如果我在 docker-compose 中定义了一个名为“my_service”的服务,我会以主机“my_service”的身份访问这个容器。
In some cases I'd like to disable a specific container and redirect all requests to it to the actual localhost, not a docker container.在某些情况下,我想禁用特定容器并将所有对它的请求重定向到实际的本地主机,而不是 docker 容器。 So instead of the host "my_service" being routed to the container with the same name, I'd like to route this to the actual localhost, where I'm running the same service eg in an IDE with a debugger attached or something similar.因此,我不想将主机“my_service”路由到具有相同名称的容器,而是将其路由到实际的本地主机,在那里我正在运行相同的服务,例如在 IDE 中连接了调试器或类似的东西。
I'm not sure how to best achieve this, whether I can modify the network itself to do this or whether I have to proxy these requests in some way.我不确定如何最好地实现这一点,我是否可以修改网络本身来做到这一点,或者我是否必须以某种方式代理这些请求。 Is there a way to do this that ideally only requires some changes in the docker-compose.yml and no changes to my containers itself?有没有办法做到这一点,理想情况下只需要对 docker-compose.yml 进行一些更改,而不需要对我的容器本身进行更改?
I'm using docker-compose on Linux (Ubuntu 20.04) or WSL2 on Windows 10.我在 Linux(Ubuntu 20.04)上使用 docker-compose 或在 Windows 10 上使用 WSL2。
You would need 3 things to make it work:你需要 3 件事来使它工作:
hostname
entry for each participating service每个参与服务的hostname
条目aliases
entry to allow other services to reach this router service via a predefined hostname.我们还将使用aliases
条目来允许其他服务通过预定义的主机名访问此路由器服务。Note: Tested for Linux.注意:针对 Linux 进行了测试。 Not sure, if it works for Windows.不确定,它是否适用于 Windows。
172.30.0.1
defined beloew, each docker service should be able to access the host.例如,通过下面定义的自定义 IP 172.30.0.1
,每个 docker 服务应该能够访问主机。docker network create \
--driver=bridge \
--subnet=172.30.0.0/16 \
--gateway=172.30.0.1 \
host-net
hostname
for each participating service in your docker-compose.yml, eg在 docker-compose.yml 中为每个参与服务添加自定义hostname
,例如services:
service-1:
hostname: service-1.in.docker
service-2:
hostname: service-2.in.docker
So, service-2
can now access to service-1
via the domain service-1.in.docker and it should work vice versa.因此, service-2
现在可以通过域 service-1.in.docker 访问service-1
,反之亦然。
services:
router:
image: alpine/socat
command: TCP-LISTEN:5900,fork TCP:172.30.0.1:15900
Here based on TCP, it listens on localhost at port 5900 and redirects the incoming requests to the destination 172.30.0.1
(the gateway -> host machine) at port 15900.这里基于 TCP,它在 localhost 的 5900 端口上监听,并将传入的请求重定向到 15900 端口的目标172.30.0.1
(网关 -> 主机)。
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:
Notes:笔记:
Here the router
service includes two important things: host-net
as network, and aliases
entry for the network bridged
, in which other services are also involved.这里的router
服务包括两个重要的东西:作为网络host-net
,以及网络bridged
的aliases
条目,其中还涉及其他服务。
The router
service works as follows: router
服务的工作原理如下:
(request) -> [localhost:5900] -> (redirect) -> [172.30.0.1:15900] (请求)-> [localhost:5900]->(重定向)-> [172.30.0.1:15900]
(request) -> [localhost:5901] -> (redirect) -> [172.30.0.1:15901] (请求)-> [localhost:5901]->(重定向)-> [172.30.0.1:15901]
Since we commented the line hostname: service-1.in.docker
, the curl requests made by service-2
( curl service-1.in.docker:5900 ) will go to the router
service (due to the alias service-1.in.docker ). Since we commented the line hostname: service-1.in.docker
, the curl requests made by service-2
( curl service-1.in.docker:5900 ) will go to the router
service (due to the alias service-1.英寸docker )。 Subsequently, these requests are forwarded to the host machine on port 15901.随后,这些请求被转发到端口 15901 上的主机。
If we comment out the line hostname: service-1.in.docker
, service-1
would respond to service2
with "hello world".如果我们注释掉这行hostname: service-1.in.docker
, service-1
会以“hello world”响应service2
。
If you have the possibility to dynamically change the hostnames used by the individual services, such as env vars or properties files etc., you can make use of them, so you don't have to comment in and out every time:如果您有可能动态更改各个服务使用的主机名,例如环境变量或属性文件等,则可以使用它们,因此您不必每次都注释掉:
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
can be provided with service-1.in.router
or service-1.in.docker
as per need. DEST_SERVICE_HOST_ADDR_SET_BY_ENV_VAR
可以根据需要与service-1.in.router
或service-1.in.docker
一起提供。
Footnote:脚注:
You can run a test server on your host maschine to test this, eg:你可以在你的主机上运行一个测试服务器来测试这个,例如:
python3 -m http.server 15901
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.