我经常看到的解决方案是将一个docker容器的端口暴露给主机。
在我的情况下,我想将一个本地端口从一个容器转发到另一个容器。
假设我在A容器上运行了一个服务,它有一个硬编码配置来访问localhost 3306上的db。但是我想在B容器上运行db服务器。
从A-localhost:3306到B-IP:3306的端口转发的最佳方法是什么?
我经常看到的解决方案是将一个docker容器的端口暴露给主机。
在我的情况下,我想将一个本地端口从一个容器转发到另一个容器。
假设我在A容器上运行了一个服务,它有一个硬编码配置来访问localhost 3306上的db。但是我想在B容器上运行db服务器。
从A-localhost:3306到B-IP:3306的端口转发的最佳方法是什么?
在您的容器中安装socat
,并在启动时运行
socat TCP-LISTEN:3306,fork TCP:B-IP:3306 &
这将在本地监听3306端口,并将任何流量双向传递到B-IP:3306
。socat可在名为socat的软件包中获得。因此,您可以运行以下任一命令来安装它:
$ yum install -y socat
$ apt install -y socat
$ apk add socat
编辑-1
您甚至可以通过不触及原始容器来完成此操作。
Dockerfile
FROM alpine
RUN apk update && apk add socat
按照以下方式构建文件
docker build -t socat .
docker run --name mysql-bridge-a-to-b --net=container:<containerAid> socat socat TCP-LISTEN:3306,fork TCP:BIP:3306
这将在A的网络上运行此容器。因此,当它在A的网络上侦听时,localhost:3306
将在A中可用,即使A容器未被触摸。
您可以使用网络模式等于主机的容器来运行。
docker run --network=host ...
在这种情况下,从容器的角度来看,localhost或127.0.0.1将指向主机。因此,如果您的数据库运行在另一个监听3306端口的B容器中,则容器A中的localhost:3306地址将连接到容器B中的数据库。
docker run -p
上公开它将透明地使其具有主机网络。 - adonesenetwork
选项将容器B设置为container
模式启动,以在容器A的网络命名空间中启动容器B。docker run --net=container:A postgres
地点:
A
是你想要映射到的容器的名称或标识符。这将在与 A
同一网络命名空间的容器中启动 postgres,因此 postgres 容器中打开的任何端口都会在与 A
相同的接口上被打开,并且应该可以在容器 A 内部的 localhost
上访问。
docker run --network=host
更为合适。 - Marinos An对于在Windows上进行开发,我们可以简单地使用host.docker.internal
:请参见docker-for-windows networking。
我想从容器连接到主机上的服务
我们建议您连接到特殊的DNS名称host.docker.internal,该名称解析为主机使用的内部IP地址。这仅用于开发目的,在Docker Desktop for Windows之外的生产环境中不起作用。
所以在您的情况下:
容器A
发布端口3306
容器B
可以简单地连接到host.docker.internal:3306
https://docs.docker.com/network/network-tutorial-standalone/
docker run --network
命令,两个镜像可以互相使用对方的名称。 - OneCricketeer这个解决方案对于所述的用例来说有些过度,但如果您在研究更大范围时遇到了这种情况。
Hashicorp Consul安装一个本地代理,将localhost端口代理到目录中注册的服务的ip地址和端口。 https://www.consul.io/intro
除了在我建立的系统中使用他们的产品外,我与Hashicorp没有任何关系。
version: '3'
services:
web:
build: .web
environment:
DB_HOST: mysql:3306 # the service name below
ports:
- "5000:5000"
mysql:
build: .mysql
ports:
- "3306:3306" # optional: used for accessing from the host, not from the other container
A:3306 -> B:3306
和C:3306 -> B:3306
进行映射,我应该启动2个socat
容器吗? - Kelvin Hudocker run --network=container:nameOrIdOfcontainerA alpine/socat TCP-LISTEN:3306,fork TCP:nameOrIpOfContainerB:3306
以及关于--network的文档。 - dlauzon