我目前遇到了一个问题,已经尝试解决了一周,却没有进展。希望你能指点我正确的方向。
初始情况
描述
我正在构建一个连接到一些API的 NestJS 应用程序。内部使用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
版本信息
工作站
- Docker版本号为19.03.13,构建版本号为4484c46d9d
- docker-compose版本号为1.27.4,构建版本号为40524192
服务器组件
- bullmq版本号为1.9.0
- ioredis版本号为4.17.3
Redis Docker
- 版本号为6.0.8
问题
我的服务器组件的问题在于它尝试使用以下代码连接到给定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'),
);
但是会抛出以下错误:
[ioredis] Unhandled error event: Error: connect ECONNREFUSED 127.0.0.1:6379
我原本以为只需在暴露端口处看到redis实例,但不在127.0.0.1看到redis实例,但不应该使用给定的ip吗?
我检查过的事情
服务器代码正确,REDIS_HOST在ioredis调用中正确提交和调用。因此,在ioredis内进一步挖掘时,我发现了这个问题。所以,考虑到所有提示,它应该是在我的工作站上作为本地可用的,我正在使用0.0.0.0:6379进行连接,并且可以正常工作。
Docker compose会自动创建网络桥,在redis docker的IP(以及别名redis和db)上使用netcat检查,服务器docker控制台上的6379端口上,redis实例是可用的。
然后,我使用docker-compose的网络配置显式设置了子网,以及为容器分配了静态IP,但正如我已经描述的那样:IP已正确解析。
我在docker github上找到了以下问题issue 204。我认为这正是我在这里面对的问题,但如何解决?
简而言之,ioredis尝试连接到正确解析的redis实例的IP,但失败了,因为该实例在服务器组件的本地IP上不可用。
我当前的状态是什么
我无法控制地哭泣。
我目前没有任何想法如何使“myserver”容器通过ioredis连接到redis实例。我认为我面临的问题必须与Windows上的Docker解析IP到127.0.0.1的方式有关。
- 我的观点正确吗?
- 你能建议其他尝试的方法吗?
此致敬礼并提前致谢。
编辑(2020-11-27):经过一些挖掘和进一步调查Jeffrey Mixon的建议,我很遗憾离解决方案还很远。我的最后几步包括:
- 更新所有依赖项(包括bullmq到v1.11,ioredis到4.19.2等)。这并没有改变任何东西。
- 然后我在bullmq issue board上找到了一个相似问题的相对较新的帖子,我从像上面展示的连接对象中重用连接切换到始终创建新连接,因为它也在bullmq文档中解释。但这也没有帮助。
new Queue(name, {
connection: {
host: this.redisHost,
port: this.redisPort,
},
})
- 我从使用IORedis库中的'Redis'对象切换为使用'IORedis',但是我的应用程序docker的习惯仍然没有改变。即使使用正确的redis主机调用Redis连接,它仍然尝试连接到上面显示的127.0.0.1:6379。
- 最后一个奇怪的行为是,如果我选择一个无法解决的主机URL,应用程序docker会正确地尝试连接到那个不可解析的主机。但是,一旦这个主机在docker-compose的网络中可用,它就会使用127.0.0.1。
编辑(2020-12-01):: 同时,我在一个干净的Linux机器上检查了一下是否仅在Windows Docker上发生问题,但是它也在Linux上发生。
我没有解决问题本身,但是我通过将所有内容放在一个docker中绕过了这个问题。由于我的应用程序更多地是一个概念验证,所以这样做没有太大的痛苦。 如果未来出现解决方案或更多人有相同的问题,我将保持这个问题开放。
对于那些想知道的人,我的dockerfile现在在redis图像之上堆叠另一层。我添加了我之前使用的ng-cli-e2e图像的部分。因此,在我的现有dockerfile的开头,我添加了以下内容:
FROM redis:6.0.9-buster
RUN apt update
RUN apt install nodejs -y
RUN apt install npm -y
最终,我创建了一个小的包装脚本,它可以启动Redis服务器和我的应用程序。现在我暴露了两个端口,以便在我的机器上访问所有内容。
EXPOSE 3000 6379
CMD ./docker-start-wrapper.sh
这不是最美观的解决方案,但目前它确实能够起到作用。
db = redis.Redis(host='db', port=6379, decode_responses=True)
。 - Hamed