seh*_*ehe 7 redis docker docker-compose ioredis
我目前遇到了一个问题,我已经尝试解决一个多星期了,但毫无进展。我希望你能指出我正确的方向。
我正在构建的项目是一个NestJS应用程序,它连接到一些 API。在内部,它使用bullmq作为消息队列,它本身使用ioredis连接到 redis 数据库。docker-compose up我已经通过以下配置连接了我自己编写的服务器组件以及redis(使用docker) :
version: '3'
services:
server:
image: myserver:1.4.0
container_name: myserver
depends_on:
- db
ports:
- 3001:3000
environment:
- REDIS_HOST=redis
db:
image: redis:6.0.8
container_name: redis
ports:
- 6379:6379
Run Code Online (Sandbox Code Playgroud)
我的服务器组件的问题是,它尝试使用以下代码连接到给定 REDIS_HOST 端口 6379 下的 redis 实例:
readonly connection = new Redis(
+(process.env.REDIS_PORT ?? this.configService.get('redis_port')),
process.env.REDIS_HOST ?? this.configService.get('redis_host'),
);
Run Code Online (Sandbox Code Playgroud)
但抛出以下错误:
[ioredis] Unhandled error event: Error: connect ECONNREFUSED 127.0.0.1:6379
Run Code Online (Sandbox Code Playgroud)
我预计它只会在暴露的端口上看到 redis 实例。
所以,它看不到 127.0.0.1 处的 redis 实例:但它不应该使用给定的 ip 吗?
服务器代码正确,REDIS_HOST在ioredis调用中正确提交和调用。所以进一步深入ioredis我发现了这个问题。因此,考虑到我的工作站本地的所有提示,它应该可用,我使用 0.0.0.0:6379 进行连接,并且工作正常。
Docker compose 会自动创建一个网桥,并使用我检查过的 netcat,redis docker 的 ip 上的端口 6379(以及别名 redis 和 db),可以从服务器 docker 控制台获取 redis 实例。
然后,我使用 docker-compose 的网络配置明确设置子网,并为容器提供静态 ip,但正如我已经描述的:ip 已正确解析。
我在 docker github issues 204上发现了以下问题。我认为这正是我在这里面临的问题,但是如何解决呢?
tl;dr ioredis 尝试连接到正确解析的 Redis 实例的 IP,但失败,因为该实例在服务器组件的本地 IP 上不可用。
我无法控制地抽泣。
我目前不知道如何让“myserver”容器通过 ioredis 连接到 redis 实例。我的观点是,我遇到的问题必须与 Windows 上的 docker 将 ips 解析为 127.0.0.1 的方式有关。。
预先致以最诚挚的问候和感谢。
编辑(2020-11-27) :经过一些挖掘和进一步调查Jeffrey Mixon的建议,不幸的是,我还没有更接近解决方案。我的最后步骤包括:
[ioredis] Unhandled error event: Error: connect ECONNREFUSED 127.0.0.1:6379
Run Code Online (Sandbox Code Playgroud)
编辑(2020-12-01):与此同时,我在一台干净的 Linux 机器上检查了问题是否只发生在 docker-for-windows 上,但它也确实发生在 Linux 上。
我本身没有解决问题,但我通过将所有内容都放在一个泊坞窗中来绕过它。由于我的应用程序更多的是概念验证,因此这样做并没有太大的痛苦。如果将来有解决方案或者更多人有同样的问题,我会保留这个问题。
对于那些想知道的人来说,我的 dockerfile(包括 redis)现在在 redis 映像之上堆叠了另一层。我正在添加我之前使用过的 ng-cli-e2e 图像中的部件。所以在我现有的 dockerfile 的开头我添加了:
FROM redis:6.0.9-buster
RUN apt update
RUN apt install nodejs -y
RUN apt install npm -y
Run Code Online (Sandbox Code Playgroud)
最后,我创建了一个小包装脚本,它只启动 redis 服务器以及我的应用程序。如果我想从我的机器访问所有内容,我现在还公开两个端口。
EXPOSE 3000 6379
CMD ./docker-start-wrapper.sh
Run Code Online (Sandbox Code Playgroud)
这不是最漂亮的解决方案,但目前确实有效。
问题是您的应用程序容器使用localhost作为连接到 redis 容器的主机名。在这种情况下,它应该使用主机名redis。
考虑以下演示:
version: '3.7'
services:
server:
image: busybox
container_name: myserver
entrypoint: /bin/sh
# if redis is replaced by localhost or 127.0.0.1 below, this container will fail
command: "-c \"sleep 2 && nc -v redis 6379\""
depends_on:
- db
ports:
- 3001:3000
environment:
- REDIS_HOST=redis
db:
image: busybox
container_name: redis
entrypoint: /bin/nc
command: "-l -p 6379 -v"
# is not necessary to publish these ports
#ports:
# - 6379:6379
Run Code Online (Sandbox Code Playgroud)
$ docker-compose -f scratch_2.yml up
Creating network "scratches_default" with the default driver
Creating redis ... done
Creating myserver ... done
Attaching to redis, myserver
redis | listening on [::]:6379 ...
myserver | redis (172.25.0.2:6379) open
redis | connect to [::ffff:172.25.0.2]:6379 from [::ffff:172.25.0.3]:34821 ([::ffff:172.25.0.3]:34821)
myserver exited with code 0
redis exited with code 0
Run Code Online (Sandbox Code Playgroud)
当您发布端口时,它们将在主机上的容器外部使用。通过尝试将mysever容器连接到127.0.0.1,容器只是尝试连接到自身。
| 归档时间: |
|
| 查看次数: |
11700 次 |
| 最近记录: |