GitHub CI部署Next.js时Docker无法找到.env.production文件
使用Docker和GitHub CI部署Next.js应用时,GitHub Actions流程执行正常,但Dockerfile引用.env.production文件时提示找不到。已尝试重命名文件、修改路径、更换SpicyPizza/create-envfile版本,且该文件未被.dockerignore或.gitignore忽略。
错误信息:
ERROR: failed to solve: process "/bin/sh -c cat .env.production && yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build" did not complete successfully: exit code: 1 Error: buildx failed with: ERROR: failed to solve: process "/bin/sh -c cat .env.production && yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build" did not complete successfully: exit code: 1
当前GitHub CI配置:
name: Docker Image CI on: push: branches: [ "main" ] jobs: build: environment: production runs-on: ubuntu-latest steps: - name: Check out the repository uses: actions/checkout@v3 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Create .env file uses: SpicyPizza/create-envfile@v2 with: envkey_EMAIL_SERVER: ${{vars.EMAIL_SERVER}} envkey_EMAIL_FROM: ${{vars.EMAIL_FROM}} envkey_EMAIL_TO: ${{vars.EMAIL_TO}} envkey_NEXT_PUBLIC_RECAPTCHA_SITE_KEY: ${{vars.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}} envkey_RECAPTCHA_SECRET_KEY: ${{secrets.RECAPTCHA_SECRET_KEY}} file_name: .env.production - name: Build and push Docker image uses: docker/build-push-action@v4 with: push: true tags: ${{ secrets.DOCKERHUB_REPO }}:latest
Dockerfile内容:
##### DEPENDENCIES FROM node:20-alpine AS deps RUN apk add --no-cache libc6-compat openssl1.1-compat WORKDIR /app # Install dependencies COPY package.json pnpm-lock.yaml* ./ RUN yarn global add pnpm && pnpm i ##### BUILDER FROM node:20-alpine AS builder WORKDIR /app COPY . . COPY --from=deps /app/node_modules ./node_modules ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED 1 RUN cat .env.production && yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build ##### RUNNER FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV production ENV NEXT_TELEMETRY_DISABLED 1 USER root RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs COPY --from=builder /app/next.config.mjs ./ 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 COPY --from=builder --chown=nextjs:nodejs .env.production ./ USER nextjs EXPOSE 3000 ENV PORT 3000 CMD ["node", "server.js"]
核心问题是**.env.production被.dockerignore规则排除,导致无法复制到Docker构建的builder阶段**。默认的Next.js项目.dockerignore通常会包含.env*这类本地环境文件,即使手动生成该文件,也会被忽略,最终导致cat .env.production执行失败。
以下是三种可行的修复方案,任选其一即可:
方案1:修改.dockerignore允许复制.env.production
在项目根目录的.dockerignore文件中添加一行,取消对.env.production的忽略:
!.env.production
如果你的.dockerignore中已有.env*或.env.production的忽略规则,这行代码会覆盖原有规则,确保该文件能被复制到构建上下文。
方案2:在Dockerfile中单独复制.env.production
先按方案1修改.dockerignore,然后在Dockerfile的builder阶段,将COPY . .替换为更精准的文件复制,同时单独指定.env.production:
##### BUILDER FROM node:20-alpine AS builder WORKDIR /app # 复制项目核心文件 COPY package.json pnpm-lock.yaml* ./ COPY next.config.mjs ./ COPY src/ ./src/ COPY public/ ./public/ # 单独复制.env.production COPY .env.production ./ COPY --from=deps /app/node_modules ./node_modules ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED 1 RUN yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build
这种方式避免了复制不必要的文件,也确保.env.production被正确复制到镜像中。
方案3:通过构建参数传递环境变量(推荐)
不需要生成.env.production文件,直接在GitHub CI中通过构建参数传递环境变量,完全规避.dockerignore的问题:
修改GitHub CI配置
在Build and push Docker image步骤中添加build-args:
- name: Build and push Docker image uses: docker/build-push-action@v4 with: push: true tags: ${{ secrets.DOCKERHUB_REPO }}:latest build-args: | EMAIL_SERVER=${{vars.EMAIL_SERVER}} EMAIL_FROM=${{vars.EMAIL_FROM}} EMAIL_TO=${{vars.EMAIL_TO}} NEXT_PUBLIC_RECAPTCHA_SITE_KEY=${{vars.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}} RECAPTCHA_SECRET_KEY=${{secrets.RECAPTCHA_SECRET_KEY}}
修改Dockerfile的builder阶段
添加构建参数声明并设置为环境变量:
##### BUILDER FROM node:20-alpine AS builder WORKDIR /app COPY . . COPY --from=deps /app/node_modules ./node_modules # 声明构建参数 ARG EMAIL_SERVER ARG EMAIL_FROM ARG EMAIL_TO ARG NEXT_PUBLIC_RECAPTCHA_SITE_KEY ARG RECAPTCHA_SECRET_KEY # 将构建参数转为环境变量 ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED 1 ENV EMAIL_SERVER=$EMAIL_SERVER ENV EMAIL_FROM=$EMAIL_FROM ENV EMAIL_TO=$EMAIL_TO ENV NEXT_PUBLIC_RECAPTCHA_SITE_KEY=$NEXT_PUBLIC_RECAPTCHA_SITE_KEY ENV RECAPTCHA_SECRET_KEY=$RECAPTCHA_SECRET_KEY RUN yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build
这种方式更安全,环境变量不会以文件形式出现在镜像中,也避免了.dockerignore的干扰。
内容的提问来源于stack exchange,提问作者user16976770

