docker - 将 docker-compose 网络内的主机重定向到 docker 外的 localhost
问题描述
我有一组使用 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 件事来使它工作:
- 预定义的外部网络,用于通过固定 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
hostname
为您的 docker-compose.yml 中的每个参与服务添加自定义,例如
services:
service-1:
hostname: service-1.in.docker
service-2:
hostname: service-2.in.docker
因此,service-2
现在可以service-1
通过域 service-1.in.docker 访问,反之亦然。
- 创建一个附加服务,利用众所周知的多用途中继工具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]
由于我们注释了该行,因此( curl service-1.in.docker:5900
hostname: service-1.in.docker
)发出的 curl 请求将转到该服务(由于别名service-1.in.docker)。随后,这些请求被转发到端口 15901 上的主机。service-2
router
如果我们注释掉该行
hostname: service-1.in.docker
,service-1
会以service2
“hello world”响应。
如果您有可能动态更改各个服务使用的主机名,例如环境变量或属性文件等,则可以使用它们,因此您不必每次都注释掉:
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
推荐阅读
- jenkins - 詹金斯奴隶没有连接
- r - R 中的 KFAS 和 dlm 包
- python - 带有变量的python原始字符串表示法。Lib.re / pypi.regex
- r - 如何根据列设置 alpha?
- php - wordpress php代码未运行(wpforms)
- c++ - leveled::DB::Open() 在我安装 leveldb 和 snappy 后未定义,macOS
- r - R - 在 gsub 之后无法计算词频
- c# - 视图中的 ASP.NET MVC 模型 (ViewModel) 三元运算符空值检查
- c# - 在我测试的软件更新后,Visual Studio 2017 中的编码 UI 测试停止工作。这会发生在其他人身上吗?
- vba - 复制粘贴过滤的数据未按预期工作