You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MacOS下Docker部署Next.js+Nginx调用后端API出现net::ERR_FAILED问题

问题原因及解决方案

核心原因

  1. 浏览器无法识别Docker内部服务域名:
    前端配置的NEXT_PUBLIC_API_BASE_URL=http://backend:5055/api中,backend是Docker Compose创建的内部服务域名,仅在容器所在的虚拟网络内可解析。但前端代码最终在浏览器(宿主机环境)运行,浏览器无法识别该内部域名,导致请求出现net::ERR_FAILED错误。

  2. SSR场景下的localhost认知误区:
    当修改配置为http://localhost:5055/api时,Next.js的SSR代码会在frontend容器内执行,此时容器内的localhost指向容器自身而非宿主机,因此出现ECONNREFUSED错误(容器内未监听5055端口)。

验证依据

  • Postman直接请求http://localhost:5055正常,是因为Postman运行在宿主机,直接访问了Docker映射到宿主机的端口。
  • Nginx容器内通过curl backend:5055/api/category/show能正常请求,说明Docker内部网络的服务通信无问题。

解决方案

方案1:利用Nginx反向代理统一请求路径

根据现有Nginx配置,已设置location /api将请求转发到http://backend,只需修改前端配置:

# frontend - .env.local
NEXT_PUBLIC_API_BASE_URL=/api

同时调整httpServices.js,区分客户端与服务端环境的API地址:

// frontend - httpServices.js
import axios from 'axios'
import Cookies from 'js-cookie'

// 判断是否为服务端环境
const isServer = typeof window === 'undefined'
const baseURL = isServer 
  ? 'http://backend:5055/api' // 服务端用Docker内部域名
  : '/api' // 客户端用相对路径

const instance = axios.create({
  baseURL,
  timeout: 500000,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
})

// ... 其余代码保持不变

这样:

  • 客户端请求:浏览器发送请求到http://localhost/api,由Nginx转发至backend容器。
  • SSR服务端请求:frontend容器内的代码直接通过Docker内部域名访问backend。

方案2:单独配置服务端API地址

若不想依赖Nginx代理服务端请求,可添加非公开环境变量:

# frontend - .env.local
NEXT_PUBLIC_API_BASE_URL=/api # 客户端使用
API_BASE_URL=http://backend:5055/api # 服务端使用,不带NEXT_PUBLIC前缀

在服务端代码(如getServerSideProps、服务端API路由)中使用process.env.API_BASE_URL,客户端代码使用process.env.NEXT_PUBLIC_API_BASE_URL。

总结

问题本质是运行环境的网络上下文差异:Docker内部服务名仅在容器网络内有效,浏览器(宿主机)与容器内的服务端代码处于不同网络环境,需分别配置对应API地址。

内容的提问来源于stack exchange,提问作者John Stuart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:01:28