将Docker容器端口暴露给其他机器

11

我使用以下命令在 Docker 中安装了 Redis

docker run -d -p 6379:6379 redis:3.0.1
docker run -d -p 6380:6379 redis:2.8.20

现在我需要从另一台机器访问这个redis实例

public static ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(IPOFDOCKERINSTALLEDMACHINE:6379);

我的应用程序托管在不同服务器的另一台机器上。

当我运行应用程序时,出现以下异常:

无法连接到Redis服务器;要创建一个已断开的复用器,请禁用AbortOnConnectFail。PING时发生SocketFailure

是否需要更改Docker或Oracle虚拟机中的任何内容?


除了在本地主机上从CLI测试连接之外,两个主机之间是否存在防火墙或其他连接限制? - BMitch
@Prithvi:Docker和连接到Redis的应用程序都在Oracle虚拟机中吗?还是连接到Redis的应用程序在Oracle虚拟机外部? - kgs
您在IPOFDOCKERINSTALLEDMACHINE的位置使用的值是什么?是您的本地主机吗? - Rao
@kgs Redis在Oracle VM“default”中的Docker中。应用程序在本地机器上。 - Prithvi Uppalapati
@Prithvi:我添加了我的答案。看看是否有帮助。 - kgs
显示剩余4条评论
6个回答

3
连接不同服务器上的多个容器跨网络进行通信是docker swarm的一个完美使用案例。您应该尝试创建一个overlay网络,并将正在运行的容器连接到swarm和该网络,如此处所述。根据您对swarm生态系统的了解,可以尝试不同的解决方案。
从Docker 1.12开始,如果您想手动管理容器,则可以运行以下命令:
# retrieve the last swarm version
$ docker pull swarm
# running your swarm manager on your server
$ docker swarm init --advertise-addr $(hostname -I | awk '{print $1}')
# creating a cross server container network
$ docker network create --driver overlay redisnet

这个命令会输出一个从节点命令,用于在您的节点上加入Swarm作为“从节点”服务器。如果您想要从该服务器启动服务,您应该输出以下命令,它将给您提供管理令牌。
$ docker swarm join-token manager

To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-1ewyz5urm5ofu78vddmrixfaye5mx0cnuj0hwxdt7baywmppav-0p5n6b7hz170gb79uuvd2ipoy \
<IP_ADDRESS>:2377

当您的节点在Swarm上时,您可以使用副本启动redis服务。
$ docker service create --network redisnet \
                        --name redis --replicas 1 redis:3.0.1
$ docker service create --network redisnet \
                        --name old_redis --replicas 1 redis:2.8.20
$ docker service create --network redisnet --name app <APP_IMAGE>

现在你所有的容器都可以使用服务名称作为特定服务的主机名进行http调用。基本上,如果你只需要从应用程序访问redis服务,那么这样做就足够了。

你也可以使用相同的docker选项-p暴露端口,但你必须发现哪个服务器运行你的服务。然而,这要求你遵循其他答案检查你的VM上是否有任何端口阻塞。

此外,还有其他解决方案,如KubernetesMesos,但swarm是官方推荐的方法。


1

根据您的错误信息;

无法连接到redis服务器;要创建一个断开连接的多路复用器,请禁用AbortOnConnectFail。PING上的SocketFailure

我认为您的另一台机器无法访问具有docker容器的机器。

  1. 尝试使用 ping IPOFDOCKERMACHINE 命令。
  2. 如果第一步不起作用,那说明您无法从其他机器访问具有 Docker 容器的机器。您需要先解决这个问题。
  3. 如果第一步成功,请尝试使用 telnet 命令确保您可以访问所需的端口。请参考 this article 中的 telnet 命令。This article 显示了如何在 Windows 操作系统中启用 telnet。 telnet IPOFDOCKERMACHINE 6380 telnet IPOFDOCKERMACHINE 6379

  4. 如果 telnet 失败,那么说明您没有访问所需端口的权限。您需要在继续之前解决此问题。

  5. 如果第三步成功,则需要确保您的 Docker 容器是按照 David Gonzalez 在他上面的回复中所示启动的。

1

Docker将您暴露的端口绑定到本地主机。这就是为什么您会遇到问题的原因。为了使Docker取消将这些暴露的端口绑定到本地主机,您必须通过更改启动容器的命令来运行容器:

docker run -d -p 0.0.0.0:6380:6379 redis:2.8.20
docker run -d -p 0.0.0.0:6379:6379 redis:3.0.1

改变的部分是现在您为本地部分指定了主机和端口(并像以前一样保留容器部分; 单个端口)。
希望这可以帮助您,朋友!请注意,这不是您通常想要实现的东西。如果您将其用于接近生产的某些内容,请确保未留下未经身份验证的redis服务。

1

如果您在运行命令时没有任何IP限制:

$ docker run -d -p 6379:6379 redis:3.0.1
$ docker run -d -p 6380:6379 redis:2.8.20

以下是显示绑定到本地主机的netstat输出:

$ netstat -na | grep 6379 && netstat -na | grep 6380 
TCP 127.0.0.1:6379 0.0.0.0:0 LISTENING

您发布到所有接口的端口与本地主机上正在侦听的端口不匹配。可能有几种可能性:

  1. 127.0.0.1:6379上有其他进程在监听。运行sudo netstat -lntp | grep 6379查找使用该端口的进程。

  2. 很可能容器没有运行。因为6380上没有任何东西。使用docker ps -a检查容器是否正在运行。如果容器正在运行,则ps输出将包括所有端口绑定。即使容器已经退出,您也可以使用docker logs container_id检查它们的日志以查看是否存在任何错误。

  3. Docker未在本地主机上运行。如果echo $DOCKER_HOST指向一个IP地址或主机名,则客户端会将命令发送到那里。如果您在VM内部运行命令并在物理主机上检查结果,则也适用此情况。

  4. 不太可能,但是您可能已使用--ip标志将默认IP更改为127.0.0.1。默认情况下,发布的端口会在所有接口(0.0.0.0)上侦听。

  5. 您上面列出的运行命令可能不准确。如果您使用docker run -d -p 127.0.0.1:6379:6379 redis:3.0.1发布了端口,则可以解释为绑定到127.0.0.1。从命令中删除127.0.0.1:将默认绑定到所有接口。


我已经重新创建了默认机器docker run -d -p 0.0.0.0:6380:6379 redis:2.8.20 docker run -d -p 0.0.0.0:6379:6379 redis:3.0.1但是我仍然遇到了以下问题:netstat -na | grep 6379 && netstat -na | grep 6380 TCP 127.0.0.1:6379 0.0.0.0:0 LISTENING请告诉我是否有做错的地方。 - Prithvi Uppalapati
netstat -a | grep 6379 TCP 127.0.0.1:6379 MY-SYS-460:0 LISTENING - Prithvi Uppalapati
1
上面的答案列出了很多解决问题的步骤。你都检查过了吗?使用你的命令重新创建容器并没有被列出,因为它不应该解决你的问题。 - BMitch
对于第一项检查。我正在使用Windows系统,netstat -lntp | grep 6379 命令似乎无效,它给出了帮助命令结果。 - Prithvi Uppalapati
@Prithvi 首先,使用 netcat 检查两个服务器之间的连通性。在运行 Redis 的服务器上,停止 Docker 并启动 nc -l 6379 监听 Redis 端口。在另一个服务器上,尝试访问监听端口 nc -v SERVERIP 6379。如果连接成功,您将看到一条消息:“Ncat:已连接到 SERVERIP:6379”。如果没有连接成功,则可能是防火墙或其他东西阻止了连接。 - Shengis

0

@Prithvi:看起来你无法从本地机器访问redis.. 你尝试在Oracle虚拟机设置中进行端口转发了吗?

enter image description here

enter image description here

通过这种方式,您可以从本地机器访问在Oracle VM中运行的应用程序。


0
暴露容器非常重要,以便主机能够识别容器运行的端口。 在docker run命令中使用-p来公开端口。 语法:docker run -p host_ip:host_port:container_port image_name(在运行时添加host_ip) docker run -d -p host_ip:6379:6379 redis:3.0.1 这将容器的端口6379绑定到主机机器上host_ip的端口6379。 使用iptables进行清除:iptables -L -n -t nat 假设容器IP为:172.17.0.2 现在发送到host_ip和端口(6379)的请求将被重定向到具有IP(172.17.0.2)和端口(6379)的容器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接