Docker中ioredis连接Redis报getaddrinfo ENOTFOUND错误解决方法
问题描述
从后端服务连接Docker部署的Redis实例时持续抛出DNS解析错误,错误日志如下:
... api-1 | [ioredis] Unhandled error event: Error: getaddrinfo ENOTFOUND undefined api-1 | at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:71:26) api-1 | [ioredis] Unhandled error event: Error: getaddrinfo ENOTFOUND undefined api-1 | at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:71:26) ...
现有配置
Redis客户端代码
import Redis from "ioredis"; export const redisConfig = () => { if (process.env.NODE_ENV === "production") { return `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`; } return ""; }; const redisCli = new Redis(redisConfig()); export default redisCli;
Dockerfile
# ---- Dependencies ---- FROM node:16-alpine AS base # minimize image size RUN apk add --no-cache libc6-compat RUN npm install -g npm@latest WORKDIR /app COPY ./package*.json ./ RUN npm ci # ---- Builder ---- FROM node:16-alpine AS builder RUN npm install -g npm@latest WORKDIR /app COPY --from=base /app/node_modules ./node_modules COPY ./src ./src COPY package*.json tsconfig.json webpack.config.ts ./ RUN npm run build # ---- Release ---- FROM node:16 AS release WORKDIR /app # COPY ./prisma ./prisma # COPY ./.env ./ # COPY ./deployment ./deployment COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./ # RUN npx prisma generate RUN npm install pm2 -g EXPOSE 3000
docker-compose.yml
version: "3" services: api: build: ./ depends_on: - redis links: - redis command: sh -c "node dist/server.js" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - NODE_ENV=production ports: - 3000:3000 redis: image: "redis:latest"
问题根因
报错核心原因是Webpack构建时静态替换了process.env变量:
- 项目使用Webpack打包后端代码,默认构建目标为
web环境,构建阶段会将代码中所有process.env.XXX的访问直接替换为构建时上下文中的对应值。 - 镜像构建的builder阶段没有传入
REDIS_HOST、REDIS_PORT、NODE_ENV等环境变量,因此process.env.REDIS_HOST被直接替换为字面量undefined,最终拼接出的Redis连接地址为redis://undefined:6379。运行时即使容器内注入了正确的环境变量,代码也不会再读取,直接对undefined这个主机名做DNS解析就会抛出ENOTFOUND错误。 - 配置中的
links参数属于Docker早期版本的遗留配置,在v3+版本Compose的默认自定义桥接网络下,服务之间默认可以通过服务名做DNS解析,不是导致本次问题的原因。
修复步骤
- 修改Webpack配置,指定构建目标为Node.js,禁止构建阶段静态替换运行时环境变量:
在webpack.config.ts中新增如下配置:
export default { // 保留原有其他配置 target: "node", // 声明构建产物运行在Node.js环境 node: { __dirname: false, __filename: false } }
- 优化Redis客户端初始化逻辑,避免隐式默认值和字符串拼接问题,改用对象形式传参更稳妥:
import Redis from "ioredis"; const redisCli = new Redis({ host: process.env.REDIS_HOST || "127.0.0.1", port: Number(process.env.REDIS_PORT) || 6379, // 配置了Redis密码的话补充password字段即可 }); export default redisCli;
- 重新构建镜像时跳过缓存,避免旧构建产物残留,在项目根目录执行如下命令重启服务:
docker compose down docker compose build --no-cache api docker compose up -d
内容的提问来源于stack exchange,提问作者retr0327
相关产品推荐
相关产品推荐

