Docker容器中Next.js 13构建失败:无法连接NestJS容器
解决Docker Compose下Next.js构建阶段无法连接NestJS容器的问题
核心原因
Docker Compose的构建阶段和运行阶段是完全隔离的:
- 构建阶段的容器默认不会加入项目的自定义Docker网络,因此即使
api容器已经启动,web容器在执行npm run build时,也无法通过服务名api解析到目标容器。 - 你大概率是在Next.js的
getStaticProps/getStaticPaths等构建时触发的函数中,直接调用了http://api/xxx这类基于服务名的接口。
解决方案
方案1:构建阶段跳过API调用(适合无需预取数据的静态页)
如果构建时不需要从API拉取数据,可以临时屏蔽或添加环境判断,仅在运行/开发阶段发起请求:
export async function getStaticProps() { // 仅在非生产构建阶段调用API if (process.env.NODE_ENV !== 'production') { const res = await fetch('http://api/api/data'); const data = await res.json(); return { props: { data } }; } // 构建阶段返回默认占位数据 return { props: { data: [] } }; }
方案2:让构建阶段加入自定义Docker网络
- 先在Compose文件中定义自定义网络:
version: '3.8' networks: app-network: driver: bridge services: api: build: ./api networks: - app-network ports: - '3001:3001' # 增加健康检查,确保API完全就绪 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/health"] interval: 5s timeout: 5s retries: 5
- 修改web服务的构建配置,让构建阶段加入自定义网络,并依赖API的健康状态:
web: build: context: ./web network: app-network # 让构建阶段加入自定义网络 networks: - app-network ports: - '3000:3000' depends_on: api: condition: service_healthy # 等待API健康检查通过再启动构建
方案3:构建阶段使用宿主机API地址(适合本地开发)
利用Docker提供的host.docker.internal域名指向宿主机,构建时直接调用宿主机上运行的API:
// 根据环境切换API地址 const apiUrl = process.env.NODE_ENV === 'production' ? 'http://api:3001' : 'http://host.docker.internal:3001'; const res = await fetch(`${apiUrl}/api/data`);
注:使用前需确保宿主机上的API服务已启动,或提前单独启动api容器。
方案4:预先生成静态数据文件(适合数据更新不频繁的场景)
提前通过脚本拉取API数据并保存为本地文件,构建时直接读取本地文件:
- 编写数据拉取脚本
fetch-data.js:
const fs = require('fs'); const fetch = require('node-fetch'); async function fetchData() { const res = await fetch('http://api:3001/api/data'); const data = await res.json(); fs.writeFileSync('./data.json', JSON.stringify(data)); } fetchData();
- 修改web容器的构建命令,先拉取数据再构建:
web: build: context: ./web network: app-network command: sh -c "node fetch-data.js && npm run build" networks: - app-network ports: - '3000:3000' depends_on: api: condition: service_healthy
内容的提问来源于stack exchange,提问作者gidgud
相关产品推荐
相关产品推荐

