DigitalOcean Docker部署Next.js构建报Firebase invalid api key错误
Next.js Docker构建阶段Firebase invalid api key报错修复
问题现象
- 部署环境:DigitalOcean Droplet,通过Docker+Traefik部署Next.js个人项目
- 报错表现:镜像构建阶段触发Firebase invalid api key错误,报错截图如下:

- 对比验证:本地执行
yarn build可正常完成构建,参考同类问题方案调整后问题仍存在;此前部署无业务代码的空Next.js项目可正常运行,加入业务代码后触发报错。
现有配置参考
Dockerfile
# Install dependencies only when needed FROM node:16-alpine AS deps RUN apk add --no-cache libc6-compat WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile # Rebuild the source code only when needed FROM node:16-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN yarn build # Production image, copy all the files and run next FROM node:16-alpine AS runner WORKDIR /app ENV NODE_ENV production RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs COPY --from=builder /app/public ./public COPY --from=builder /app/package.json ./package.json COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs EXPOSE 3000 ENV PORT 3000 CMD ["node", "server.js"]
docker-compose.yml
version: "3.3" services: traefik: image: "traefik:v2.7" container_name: "traefik" command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--certificatesresolvers.myresolver.acme.email=my_email@mail.com" - "--certificatesresolvers.myresolver.acme.storage=acme.json" - "--certificatesresolvers.myresolver.acme.httpchallenge=true" - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" ports: - "80:80" - "443:443" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" project_name: build: project_name-frontend/. labels: - "traefik.enable=true" - "traefik.http.routers.domain_name.rule=Host(`my_domain.com`) || Host(`www.my_domain.com`)" - "traefik.http.routers.domain_name.entrypoints=websecure" - "traefik.http.routers.domain_name.tls=true" - "traefik.http.routers.domain_name.tls.certresolver=myresolver" - "traefik.http.routers.http-catchallwww.rule=Host(`www.domain_name.com`)" - "traefik.http.routers.http-catchallwww.entrypoints=web" - "traefik.http.routers.http-catchallwww.middlewares=redirect-to-https@docker" - "traefik.http.middlewares.http-catchallwww.redirectscheme.scheme=https" - "traefik.http.middlewares.www-redirect.redirectregex.regex=^https://www.my_domain.com/(.*)" - "traefik.http.middlewares.www-redirect.redirectregex.replacement=https://my_domain.com/$${1}" - "traefik.http.middlewares.www-redirect.redirectregex.permanent=true" - "traefik.http.routers.http-catchallwww.middlewares=www-redirect" environment: NEXT_PUBLIC_FRONTEND_URL: https://my-domain.com MONGO_URI: my_mongo_uri //more env variables
根因定位
核心问题是环境变量注入时机错误:
- Next.js中所有带
NEXT_PUBLIC_前缀的变量(包括Firebase客户端初始化需要的API Key等配置),会在yarn build执行阶段被静态替换打包到客户端JS代码中,属于构建时变量。 - 当前配置把所有环境变量写在docker-compose的
environment字段下,这类变量只会在容器启动运行时加载,镜像构建的builder阶段完全读取不到这些值,Firebase初始化时拿到的API Key为undefined,自然触发invalid api key报错。 - 本地构建能正常运行,是因为本地目录下存在
.env.local/.env.development等环境变量文件,构建时Next.js自动读取到了正确的Firebase配置。
修复方案
- 方案1:通过build args注入构建时变量
- 修改docker-compose.yml中project_name服务的build配置,把所有构建阶段需要的
NEXT_PUBLIC_*变量、Firebase配置通过build args传入:
build: context: project_name-frontend/. args: NEXT_PUBLIC_FIREBASE_API_KEY: 替换为你的实际Firebase API Key NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: 替换为你的实际Firebase Auth域名 NEXT_PUBLIC_FIREBASE_PROJECT_ID: 替换为你的实际Firebase项目ID # 其余所有NEXT_PUBLIC_开头的、构建阶段需要读取的变量都在此处声明- 修改Dockerfile的builder阶段,在
RUN yarn build前添加ARG声明并转为构建时可用的环境变量:
# 放在COPY . . 之后,RUN yarn build之前 ARG NEXT_PUBLIC_FIREBASE_API_KEY ARG NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ARG NEXT_PUBLIC_FIREBASE_PROJECT_ID # 对应上面传入的所有args逐一声明 ENV NEXT_PUBLIC_FIREBASE_API_KEY=$NEXT_PUBLIC_FIREBASE_API_KEY ENV NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=$NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ENV NEXT_PUBLIC_FIREBASE_PROJECT_ID=$NEXT_PUBLIC_FIREBASE_PROJECT_ID - 修改docker-compose.yml中project_name服务的build配置,把所有构建阶段需要的
- 方案2:构建阶段加载生产环境变量文件
在服务器的项目目录下提前创建.env.prod文件,写入所有生产环境变量(包括Firebase配置、NEXT_PUBLIC_*变量),在Dockerfile的builder阶段确认该文件被复制到镜像工作目录,Next.js构建时会自动读取该文件内的配置。注意:不要把生产环境变量文件提交到公开代码仓库 - 额外排查项
- 确认配置的Firebase API Key没有多余的空格、换行符,和Firebase控制台给出的值完全一致
- 检查Firebase控制台的API Key限制规则,确认Droplet出口IP、生产域名已加入允许列表,没有被拦截
- 纯服务端使用的变量(比如
MONGO_URI)不需要在构建阶段注入,保留在docker-compose的environment字段下即可,这类变量是运行时读取的,不影响构建过程
内容的提问来源于stack exchange,提问作者Loudrous
相关产品推荐
相关产品推荐

