无法从另一个Docker容器连接到Redis

12

我正在Docker容器中运行redis-server。它在127.0.0.1端口6379上运行。

在容器内: 当我在容器内部时,能够连接到redis-server并处理命令,没有问题。

从主机: 当我使用redis-cli monitor从主机连接到容器时,它会出现错误:Error: Server closed the connection。

如果我只是执行redis-cli,它会给出提示符;

127.0.0.1:6379> 
127.0.0.1:6379> set www yee
Error: Server closed the connection

看起来Docker已经正确暴露了端口,并且端口映射已经生效,连接的失败不在于建立连接,而是连接很快就被终止了。

从同一Docker(桥接)网络上的另一个容器中:

redis.on('error', function(err) {    
        logger.error('Redis error: ' + err);
    } );

Redis error: Redis connection to 172.18.0.2:6379 failed - connect ECONNREFUSED 172.18.0.2:6379

我的redis.conf文件中设置了protected-mode no

日志级别设置为debug,但日志中没有显示任何有关连接尝试和拒绝的信息。

Redis客户端在超时时会不断重试,但每次都会收到连接被拒绝的消息。我已经尝试使用Docker网络中的容器名称(作为主机名)和容器IP地址,但结果相同。

docker network create redisnet
docker run --name redis -p 6379:6379 -d --net "redisnet" redis-server
docker run --name apiserver -p 81:8080 --net "redisnet" -d api-server

If I try to ping it from another container on the same net:
docker run -it --rm --net redisnet redis redis-cli -h redis ping
Could not connect to redis at redis:6379: Connection refused

如果有任何调试技巧,这将非常有帮助;


你是否在启动Docker或在Dockerfile中构建时暴露了端口6379? - Alejandro Galera
是的,我确实暴露了6379端口。但似乎暴露命令只是为了说明该端口可用,并不会发布该端口。您必须使用“-p”来发布该端口。 - nishant
4个回答

15

要从主机与容器进行通信,您需要在主机上发布端口。例如:docker run -p 6379:6379 redis。没有必要暴露该端口。这会使服务对网络上的所有内容都可用。您可以通过指定要监听的接口来限制其范围,例如:docker run -p 127.0.0.1:6379:6379 -d redis

要在容器之间通信,它们需要位于同一个用户创建的Docker网络上。例如:

docker network create my_app
docker run --net my_app -d --name redis redis

接下来,您将能够将其他容器连接到相同的网络并与“redis:6379”进行通信。例如:

$ docker run -it --rm --net my_app redis redis-cli -h redis ping
PONG

它们在同一个网络上,并且我已经使用了 -p 选项。当我运行 docker ps 命令时,它显示了以下内容:1db4378805f0 redis-server 0.0.0.0:6379->6379/tcp Redis。但是,当我运行 PONG 命令时,它仍然显示连接被拒绝。 - nishant
很难调试我们看不到的镜像。如果你正在创建自己的镜像并在请求帮助时,请包含 Dockerfile 文件是最好的方式。否则,如果没有看到你的命令,通常会假定你正在使用已经存在且监听 0.0.0.0:6379 的 redis 镜像。 - BMitch
谢谢你的鼓舞人心的回答,但是我们如何从容器中访问主机redis呢? - L_K
我需要多执行一步,才能获取源的正确IP地址:docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis对我来说输出是172.19.0.2。然后我可以像这样从主机连接到源:redis-cli -h 172.19.0.2 -p 6379 - ChrisDanger

15

我通过注释redis.conf文件中以下行来解决了这个问题。

# bind 127.0.0.1
当Redis在容器中启动并连接到Docker网络时,该网络上会为Redis创建一个新的接口,并且该接口具有自己的IP地址。例如,Docker网络可以在范围内分配地址172.18.0.2/24,Redis容器可以被分配172.18.0.2。除非在docker run命令中显式分配IP地址,否则通常无法预测将分配给Redis的IP地址。唯一的选择是在redis.conf中注释绑定操作,这将允许Redis现在在所有接口上监听对6379的请求。
这解决了问题,我能够从另一个容器连接到Redis。

2
不要在Docker中暴露端口6379,如果这样做,任何拥有你的IP地址的人都可以连接/尝试暴力破解你的Redis。感谢提供解决方案。 - Bast

5

在创建容器时,使用-p选项将redis容器端口映射到主机端口。例如:

sudo docker run  -p 6379:6379 --name containername imageId

然后,您可以在主机机器上访问容器内运行的Redis。

2

虽然连接已经建立,但我无法ping ing redis-cli。我通过在redis.conf中将bind 127.0.0.1改为bind 0.0.0.0解决了这个问题。


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