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

如何让Docker环境变量在容器构建和运行阶段均可用?

问题修复与优化方案

一、GitLab CI构建失败修复

失败原因

你本地通过docker-compose触发构建时,compose会自动将build.args下的参数传递给docker build进程,但GitLab CI的脚本中直接调用docker build命令,没有传递任何构建参数,导致Dockerfile里的ARG API_URL、ARG NEXT_PUBLIC_CLIENT_API_URL拿到的是空值。Next.js构建阶段如果存在预请求接口的逻辑(比如getStaticProps、服务端组件初始化请求),空的API_URL会默认指向127.0.0.1,就会抛出你遇到的连接拒绝错误。

修复步骤

  1. 先将API_URL、NEXT_PUBLIC_CLIENT_API_URL两个变量配置到GitLab项目的CI/CD变量库中(路径:项目设置→CI/CD→变量,敏感值请不要勾选「暴露给管道日志」)
  2. 修改CI脚本的docker build命令,新增--build-arg传递构建参数:
...
Build and Push App:
  image: docker:19.03.5
  services:
    - docker:19.03.5-dind
  stage: Build and Push
  script:
    - apk add python3
    - pip3 install awscli
    # 新增--build-arg传递构建参数,变量值从GitLab CI变量中读取
    - docker build --compress \
        --build-arg API_URL=$API_URL \
        --build-arg NEXT_PUBLIC_CLIENT_API_URL=$NEXT_PUBLIC_CLIENT_API_URL \
        -t $ECR_REPO:$CI_COMMIT_SHORT_SHA .
    - $(aws ecr get-login --no-include-email --region ap-south-1)
    - docker push $ECR_REPO:$CI_COMMIT_SHORT_SHA
    - docker tag $ECR_REPO:$CI_COMMIT_SHORT_SHA $ECR_REPO:latest
    - docker push $ECR_REPO:latest
  rules:
    - if: '$CI_COMMIT_BRANCH =~ /^(main|production)$/'
...

二、docker-compose重复传变量的问题

你本地需要同时传两次变量是正常逻辑,不存在冗余,两者作用阶段完全不同:

  • build.args下的变量是构建阶段使用,只会在docker build时传递给Dockerfile的ARG指令,容器运行时无法读取这些值
  • environment下的变量是容器运行阶段使用,只会在容器启动时注入到容器的环境变量中,构建阶段完全看不到这些值

优化方案(避免重复写变量值)

可以通过.env文件统一管理所有变量,不需要在docker-compose里硬写两遍值:

  1. 项目根目录新建.env文件:
API_URL=http://path-to-my-external-api-url
NEXT_PUBLIC_CLIENT_API_URL=http://path-to-my-external-api-url
NODE_ENV=production
  1. 修改docker-compose.yml,直接读取.env的变量:
version: "3.7"
# 声明加载根目录.env文件,也可以省略不写,docker-compose默认会加载
env_file: .env
services:
  app:
    container_name: frontend
    build: 
      context: .
      args:
        - API_URL=${API_URL}
        - NEXT_PUBLIC_CLIENT_API_URL=${NEXT_PUBLIC_CLIENT_API_URL}
    environment:
      - NODE_ENV=${NODE_ENV}
      - API_URL=${API_URL}
      - NEXT_PUBLIC_CLIENT_API_URL=${NEXT_PUBLIC_CLIENT_API_URL}
    ports:
      - "3000:3000"
  nginx:
    depends_on: 
      - app
    container_name: frontend-nginx
    build: ./nginx
    ports:
      - "8080:8080"

后续修改变量只要改.env文件即可,不需要调整docker-compose配置。

额外优化建议

  • Dockerfile里的ARG声明可以提前到对应FROM语句之后,避免不必要的分层缓存失效
  • NEXT_PUBLIC_开头的变量会被打包到客户端静态代码中,如果运行时不需要修改,运行时的environment可以不用传这个变量
  • 如果使用Next.js 13.4+版本,支持运行时公共变量替换,可以不用在构建阶段传NEXT_PUBLIC_前缀变量,灵活度更高

内容的提问来源于stack exchange,提问作者dEBA M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:15:00