Docker内运行的Apollo Server 4.0无法连接本地Redis缓存
问题描述
目标是在AWS Fargate上部署使用AWS Redis缓存服务的Apollo Graph 4.0订阅服务器,计划先完成本地调试再迁移至AWS。本地操作步骤如下:
- 安装本地Redis服务,端口为
localhost:6379; - 通过
ping命令确认Redis正常运行,收到pong响应; - 直接在终端运行Apollo Server 4.0,可正常连接Redis并运行;
- 构建Docker镜像(命令:
docker build -t apollo-server .),并尝试以下命令启动容器:docker run --network host apollo-server docker run --network host -p 6379:6379 apollo-server docker run --network host -p 4500:4500 apollo-server - Apollo Graph服务器启动时出现错误:
Error: connect ECONNREFUSED 127.0.0.1:6379
Dockerfile内容
FROM node:16-alpine ENV NODE_ENV=development WORKDIR /src COPY package*.json ./ RUN npm install COPY . . EXPOSE 4500 CMD ["npm", "start"]
Apollo Graph 4.0服务器核心代码片段
import Keyv from "keyv"; import { KeyvAdapter } from "@apollo/utils.keyvadapter"; const isLocal = process.env.NODE_ENV === 'development'; const redisUrl = isLocal ? 'redis://localhost:6379' : 'redis://xxx:xxxxx@cacheforsubscriptionserver-sl5gpo.serverless.use2.cache.amazonaws.com:6379'; const keyv = new Keyv(redisUrl); // 其余服务器代码省略...
完整错误信息
Error: connect ECONNREFUSED 127.0.0.1:6379
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1278:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 6379
}
解决方案
问题根源
容器内的localhost指向容器自身,而非宿主机的localhost。即使使用--network host,不同系统的表现存在差异:
- Linux系统下,
--network host会让容器直接使用宿主机网络,此时localhost能访问宿主机Redis,但需要确认Redis配置是否允许外部连接(比如绑定地址不是127.0.0.1而是0.0.0.0); - macOS/Windows系统下,Docker Desktop的
host网络模式并不完全等效于Linux,容器无法直接通过localhost访问宿主机服务,需要用宿主机的局域网IP或者Docker Desktop提供的特殊地址host.docker.internal。
具体修复方案
方案1:替换localhost为宿主机可访问地址
将代码中的Redis地址改为宿主机的局域网IP,或者在Docker Desktop环境下使用host.docker.internal:
// 修改Redis地址配置 const redisUrl = isLocal ? 'redis://host.docker.internal:6379' : 'redis://xxx:xxxxx@cacheforsubscriptionserver-sl5gpo.serverless.use2.cache.amazonaws.com:6379';
启动容器时无需--network host,直接用默认桥接网络即可:
docker run -p 4500:4500 apollo-server
方案2:调整Redis绑定地址(仅Linux系统)
修改Redis配置文件(通常路径为/etc/redis/redis.conf):
- 将
bind 127.0.0.1改为bind 0.0.0.0,允许所有IP访问; - 重启Redis服务:
sudo systemctl restart redis
之后用--network host启动容器,容器内的localhost会指向宿主机,即可正常连接Redis。
方案3:使用Docker自定义网络
创建自定义网络让Redis和Apollo容器互通:
- 创建网络:
docker network create apollo-redis-net - 启动Redis容器并加入网络:
docker run --name redis --network apollo-redis-net -p 6379:6379 redis - 修改Apollo代码中的Redis地址为容器名
redis:
const redisUrl = isLocal ? 'redis://redis:6379' : 'redis://xxx:xxxxx@cacheforsubscriptionserver-sl5gpo.serverless.use2.cache.amazonaws.com:6379';
- 构建镜像后启动容器:
docker run --name apollo-server --network apollo-redis-net -p 4500:4500 apollo-server
额外注意事项
- 本地开发时建议用环境变量传递Redis地址,避免硬编码,方便切换环境;
- 部署到AWS Fargate时,需确保ElastiCache Redis的安全组允许Fargate任务所在安全组访问6379端口,同时Redis地址配置正确。
内容的提问来源于stack exchange,提问作者user1952069
相关产品推荐
相关产品推荐

