Docker中使用Redis的NestJS应用程序出现Unhandled error event错误

47次阅读
没有评论

问题描述

在使用Docker中运行Redis的NestJS应用程序时遇到了Unhandled error event错误。他的NestJS应用程序在本地使用Homebrew安装的Redis上正常运行。然后,他在远程Docker实例中安装了Redis,并将本地环境配置为指向该Redis实例。他将NestJS应用程序容器化并发布到与Redis相同的Docker中。配置与本地环境相同,并且Redis配置指向Docker主机IP(而不是localhost或127.0.0.1)。他遇到了以下错误:

[ioredis] Unhandled error event: Error: connect ECONNREFUSED 127.0.0.1:6379    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16)

以下是他的代码片段:

export const RedisSettings: RedisOptions = {
  host: process.env.REDIS_HOST || 'localhost',
  port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT, 10) : 6379,
};

const bootstrap = async () => {
  console.log(green(`Redis on ${ process.env.REDIS_HOST }:${ process.env.REDIS_PORT }`));
  const app = await NestFactory.create(AppModule, {
    logger: ['error', 'warn', 'log', 'debug', 'verbose'],
  });
  app.enableCors();
  const staticPath = join(process.cwd(), '_html/');
  app.use(express.static(staticPath));
  const port = process.env.PORT || 3000;
  await app.listen(port);
  console.log(cyan(`\n\nServing on http://localhost:${ port }`));
};
void bootstrap();

用户希望得到一些提示来解决这个问题。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

根据错误信息,连接被拒绝,因为Redis客户端正在尝试连接到本地主机(127.0.0.1)的Redis实例。在Docker容器中,容器内部的网络环境与主机环境是隔离的,因此容器内部无法直接访问主机的Redis实例。为了解决这个问题,你需要将Redis配置更改为连接到Docker网络中的Redis实例。
以下是解决方案的步骤:
1. 确保Redis容器已经正确运行,并且可以通过Docker主机的IP地址访问。
2. 在NestJS应用程序的环境变量中设置正确的Redis主机和端口。
– 如果你的Redis容器在Docker网络中的名称为redis,则将REDIS_HOST设置为redis
– 如果你的Redis容器在Docker网络中的IP地址为172.17.0.2,则将REDIS_HOST设置为172.17.0.2
– 将REDIS_PORT设置为Redis容器的端口(默认为6379)。
3. 更新NestJS应用程序的Redis配置,使用环境变量中的值:

export const RedisSettings: RedisOptions = {
  host: process.env.REDIS_HOST || 'localhost',
  port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT, 10) : 6379,
};
  1. 重新构建和运行NestJS应用程序的Docker容器。
  2. 确保NestJS应用程序容器能够成功连接到Redis容器。

方案2

如果你的NestJS应用程序和Redis容器在同一个Docker网络中,并且你已经正确配置了Redis主机和端口,但仍然遇到连接问题,可能是由于网络延迟或容器启动顺序导致的。在这种情况下,你可以尝试使用一些延迟启动容器的方法来确保Redis容器在NestJS应用程序容器之前启动。
以下是一个示例的Docker Compose文件,使用depends_on属性来控制容器的启动顺序:

version: '3'
services:
  redis:
    image: redis
    # Redis容器的其他配置

  nestjs:
    build: .
    depends_on:
      - redis
    # NestJS应用程序容器的其他配置

在上面的示例中,我们定义了两个服务redisnestjsnestjs服务使用depends_on属性指定依赖于redis服务。这将确保Redis容器在NestJS应用程序容器之前启动。
请注意,depends_on属性并不能保证Redis容器的完全可用性。如果Redis容器需要一些额外的时间来准备并变为可连接状态,你可能需要在NestJS应用程序中添加一些逻辑来等待Redis容器就绪。

方案3

如果你的NestJS应用程序和Redis容器在不同的Docker网络中,你需要确保两个容器可以相互访问。你可以使用Docker的网络连接功能来实现这一点。
以下是解决方案的步骤:
1. 创建一个自定义的Docker网络:

docker network create mynetwork
  1. 将Redis容器连接到自定义网络:
docker run -d --name redis --network=mynetwork redis
  1. 将NestJS应用程序容器连接到自定义网络,并设置正确的Redis主机和端口:
docker run -d --name nestjs --network=mynetwork -e REDIS_HOST=redis -e REDIS_PORT=6379 your_image

请注意,上述命令中的your_image应替换为你的NestJS应用程序的Docker镜像名称。
通过将Redis容器和NestJS应用程序容器连接到相同的自定义网络,它们可以相互访问,并且NestJS应用程序可以使用REDIS_HOSTREDIS_PORT环境变量来连接到Redis容器。

以上是解决这个问题的几种可能的方案。根据你的具体情况选择适合你的方案,并根据需要进行相应的配置和调整。希望这些解决方案能帮助你解决问题!

正文完