Docker Compose构建NextJS应用时MongoDB与Redis连接失败
NextJS + Docker Compose构建阶段无法连接MongoDB/Redis的问题
我有一个基于NextJS的应用,使用MongoDB和Redis作为数据存储,尝试通过Docker Compose部署时遇到问题:在NextJS构建的Generating static pages阶段,应用需要连接Redis和MongoDB获取静态页面数据,但此时这两个服务的容器尚未启动,导致连接失败,出现以下错误:
Redis连接错误
42.85 [ioredis] Unhandled error event: Error: getaddrinfo ENOTFOUND redis_pishrun 42.85 at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:107:26) 42.85 at GetAddrInfoReqWrap.callbackTrampoline (node:internal/async_hooks:128:17)
MongoDB连接错误
73.84 MongooseServerSelectionError: getaddrinfo ENOTFOUND mongo_pishrun 73.84 at _handleConnectionErrors (/app/node_modules/mongoose/lib/connection.js:909:11) 73.84 at NativeConnection.openUri (/app/node_modules/mongoose/lib/connection.js:860:11) { 73.84 reason: TopologyDescription { 73.84 type: 'Unknown', 73.84 servers: Map(1) { 'mongo_pishrun:27017' => [ServerDescription] }, 73.84 stale: false, 73.84 compatible: true, 73.84 heartbeatFrequencyMS: 10000, 73.84 localThresholdMS: 15, 73.84 setName: null, 73.84 maxElectionId: null, 73.84 maxSetVersion: null, 73.84 commonWireVersion: 0, 73.84 logicalSessionTimeoutMinutes: null 73.84 }, 73.84 code: undefined, 73.84 digest: '2271496410' 73.84 }
我的配置文件
docker-compose.yml
version: '3.8' services: pishrun-next: container_name: pishrun-next restart: always build: context: . dockerfile: Dockerfile args: ENV_VARIABLE: ${ENV_VARIABLE} NEXT_PUBLIC_ENV_VARIABLE: ${NEXT_PUBLIC_ENV_VARIABLE} ports: - '3000:3000' networks: - shared_network depends_on: - mongo_pishrun - redis_pishrun mongo_pishrun: image: mongo:latest container_name: mongo_pishrun restart: always ports: - '27017:27017' volumes: - mongo_pishrun_data:/data/db environment: - MONGO_INITDB_ROOT_USERNAME=root - MONGO_INITDB_ROOT_PASSWORD=Aa!23456 networks: - shared_network redis_pishrun: image: redis:latest container_name: redis_pishrun restart: always ports: - '6379:6379' networks: - shared_network volumes: - redis_pishrun_data:/data volumes: mongo_pishrun_data: driver: local redis_pishrun_data: driver: local networks: shared_network: external: true
NextJS应用的Dockerfile
FROM node:18-alpine WORKDIR /app COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ RUN npm i COPY . . ARG ENV_VARIABLE ENV ENV_VARIABLE=${ENV_VARIABLE} ARG NEXT_PUBLIC_ENV_VARIABLE ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE} RUN npm run build CMD npm run start
已尝试的解决方案
- 为容器创建共享网络
- 单独运行Redis和MongoDB容器后再构建NextJS容器
- 在构建过程中添加网络作为构建参数:
docker compose -f docker-compose.yml build --build-arg NETWORK=shared_network
问题仍未解决,Docker构建阶段似乎无法访问Docker网络。
解决方案
核心原因
Docker的构建阶段与运行阶段完全隔离:构建过程在临时构建容器中执行,该容器不会自动加入docker-compose定义的网络,因此即使提前启动MongoDB/Redis容器,构建阶段也无法通过容器名解析到对应服务。
可行方案
方案1:本地预构建静态产物,再打包镜像
在本地环境(或CI/CD环境)先完成NextJS构建(确保本地能连接MongoDB/Redis获取数据),再将构建产物复制到镜像中,避免在镜像构建阶段执行build命令。修改Dockerfile:
FROM node:18-alpine WORKDIR /app # 复制预构建的静态产物 COPY .next/ .next/ COPY public/ public/ COPY package.json ./ ARG ENV_VARIABLE ENV ENV_VARIABLE=${ENV_VARIABLE} ARG NEXT_PUBLIC_ENV_VARIABLE ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE} # 只安装生产依赖 RUN npm install --production CMD npm run start
执行流程:本地运行npm run build → 执行docker compose build → docker compose up
方案2:用Docker Buildkit让构建阶段加入现有网络
启用Docker Buildkit,让构建阶段的容器加入已存在的shared_network,从而能访问MongoDB/Redis服务:
- 确保Buildkit已启用(通过环境变量
DOCKER_BUILDKIT=1开启) - 修改docker-compose.yml的build配置,添加network字段:
build: context: . dockerfile: Dockerfile args: ENV_VARIABLE: ${ENV_VARIABLE} NEXT_PUBLIC_ENV_VARIABLE: ${NEXT_PUBLIC_ENV_VARIABLE} network: shared_network
- 提前启动MongoDB和Redis容器:
docker compose up -d mongo_pishrun redis_pishrun - 执行构建命令:
DOCKER_BUILDKIT=1 docker compose build
方案3:改用NextJS增量静态再生(ISR)
修改页面的静态生成逻辑,使用增量静态再生,让页面在首次请求时生成,而非构建阶段。这样构建阶段无需依赖外部服务,运行时再获取数据。示例:
export async function getStaticProps() { // 从MongoDB/Redis获取数据的逻辑 const data = await fetchRequiredData(); return { props: { data }, // 每60秒自动重新生成页面(可按需调整) revalidate: 60, }; }
内容的提问来源于stack exchange,提问作者Trucker
相关产品推荐
相关产品推荐

