如何正确连接Docker化的Next.js前端与Strapi后端API?
问题根因
这个问题是Next.js双渲染机制+Docker内网域名解析规则共同导致的:
- Next.js的SSG/SSR阶段请求API是在Docker前端容器内部执行,同网络下你的Strapi容器名就是
<myapi.com>,所以域名会被解析为Docker内网IP - 客户端渲染阶段请求是在用户浏览器执行,需要走公网HTTPS地址,用HTTP就会触发混合内容错误,而Docker内网IP没有配置SSL证书,直接用HTTPS访问内网IP会校验失败
最优解决方案:拆分服务端/客户端API地址
这个方案可以同时兼顾内网调用效率和客户端兼容性,不需要修改网络配置:
- 拆分环境变量
不需要在Next.js的Dockerfile里硬编码API地址,删除Dockerfile中所有ENV NEXT_PUBLIC_STRAPI_API_URL相关的行,改为在docker-compose中配置两类环境变量:- 带
NEXT_PUBLIC前缀的变量:客户端可访问,配置为公网HTTPS的API地址,不用带端口(nginx-proxy默认监听443端口) - 不带前缀的变量:仅服务端可访问,配置为Docker内网服务名直接调用
修改后的docker-compose frontend配置如下:
frontend: # 注意你原来的配置里打错成了frontent,记得修正 image: frontend:latest restart: always ports: - "1338:3000" depends_on: - backend environment: VIRTUAL_HOST: <myfrontend.com> LETSENCRYPT_HOST: <myfrontend.com> # 客户端用公网HTTPS地址 NEXT_PUBLIC_STRAPI_API_URL: https://<myapi.com> # 服务端用内网HTTP地址,不会触发混合内容校验 STRAPI_API_URL: http://backend:1337 container_name: <myfrontend.com> - 带
- 修改API请求逻辑
在你封装请求的公共代码中,判断当前运行环境选择对应地址:const baseURL = typeof window === 'undefined' ? process.env.STRAPI_API_URL : process.env.NEXT_PUBLIC_STRAPI_API_URL // 将baseURL传入axios实例配置即可 - 修正Strapi公共地址
在Strapi的配置文件中把publicURL设置为https://<myapi.com>,确保返回的资源链接(如图片、附件)都是HTTPS协议,避免混合内容错误。
备用方案:强制Docker走公网DNS解析
如果不想修改业务代码,可以直接修改前端容器的DNS配置,让内部解析域名时走公网DNS,不会解析到内网IP:
在docker-compose的frontend配置中添加dns项即可:
frontend: # 其他配置保持不变 dns: - 8.8.8.8 - 223.5.5.5
该方案的缺点是API请求会走公网绕一圈,调用效率低于内网直接调用的方案。
内容的提问来源于stack exchange,提问作者YannickAaron
相关产品推荐
相关产品推荐

