簡體   English   中英

將 docker-compose 網絡內的主機重定向到 docker 外的 localhost

[英]Redirect host inside docker-compose network to localhost outside docker

我有一組使用 docker-compose 運行的容器。 該網絡是 docker-compose 創建的默認網絡,容器使用 docker-compose 自動設置的主機名相互通信。 因此,如果我在 docker-compose 中定義了一個名為“my_service”的服務,我會以主機“my_service”的身份訪問這個容器。

在某些情況下,我想禁用特定容器並將所有對它的請求重定向到實際的本地主機,而不是 docker 容器。 因此,我不想將主機“my_service”路由到具有相同名稱的容器,而是將其路由到實際的本地主機,在那里我正在運行相同的服務,例如在 IDE 中連接了調試器或類似的東西。

我不確定如何最好地實現這一點,我是否可以修改網絡本身來做到這一點,或者我是否必須以某種方式代理這些請求。 有沒有辦法做到這一點,理想情況下只需要對 docker-compose.yml 進行一些更改,而不需要對我的容器本身進行更改?

我在 Linux(Ubuntu 20.04)上使用 docker-compose 或在 Windows 10 上使用 WSL2。

tl;博士

你需要 3 件事來使它工作:

  1. 用於通過固定 IP 訪問主機的預定義外部網絡
  2. 每個參與服務的hostname條目
  3. 一個附加的 Docker 服務作為路由器,以便將請求重定向到主機。 我們還將使用aliases條目來允許其他服務通過預定義的主機名訪問此路由器服務。

如何

注意:針對 Linux 進行了測試。 不確定,它是否適用於 Windows。

  1. 使用網關創建外部網絡。 例如,通過下面定義的自定義 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. 在 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 ,反之亦然。

  1. 創建一個附加服務,利用眾所周知的多用途中繼工具socat來充當路由器,例如
services:
    router:
        image: alpine/socat
        command: TCP-LISTEN:5900,fork TCP:172.30.0.1: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:

筆記:

  1. 這里的router服務包括兩個重要的東西:作為網絡host-net ,以及網絡bridgedaliases條目,其中還涉及其他服務。

  2. router服務的工作原理如下:

(請求)-> [localhost:5900]->(重定向)-> [172.30.0.1:15900]

(請求)-> [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.英寸docker )。 隨后,這些請求被轉發到端口 15901 上的主機。

  2. 如果我們注釋掉這行hostname: service-1.in.dockerservice-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.routerservice-1.in.docker一起提供。

腳注:

你可以在你的主機上運行一個測試服務器來測試這個,例如:

python3 -m http.server 15901

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM