简体   繁体   English

将 docker-compose 网络内的主机重定向到 docker 外的 localhost

[英]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。

tl;dr tl;博士

You would need 3 things to make it work:你需要 3 件事来使它工作:

  1. A predefined external network for access to the host via a fixed IP用于通过固定 IP 访问主机的预定义外部网络
  2. hostname entry for each participating service每个参与服务的hostname条目
  3. An additional Docker service as router in order to redirect requests to the host.一个附加的 Docker 服务作为路由器,以便将请求重定向到主机。 We will also use the aliases entry to allow other services to reach this router service via a predefined hostname.我们还将使用aliases条目来允许其他服务通过预定义的主机名访问此路由器服务。

How to如何

Note: Tested for Linux.注意:针对 Linux 进行了测试。 Not sure, if it works for Windows.不确定,它是否适用于 Windows。

  1. Create the external network with a gateway.使用网关创建外部网络。 Eg via the custom IP 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
  1. Add custom 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 ,反之亦然。

  1. Create an additional service that utilizes the well-known multipurpose relay tool socat to act like a router, eg创建一个附加服务,利用众所周知的多用途中继工具socat来充当路由器,例如
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 (网关 -> 主机)。

Example例子

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:笔记:

  1. 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 ,以及网络bridgedaliases条目,其中还涉及其他服务。

  2. 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]

  1. 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 上的主机。

  2. If we comment out the line hostname: service-1.in.docker , service-1 would respond to service2 with "hello world".如果我们注释掉这行hostname: service-1.in.dockerservice-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.routerservice-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM