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

如何在Google Cloud Build中为多阶段Dockerfile配置构建缓存?

问题:Cloud Build多阶段Docker构建未命中缓存

我在Google Cloud Build中使用多阶段Dockerfile构建项目,按照官方加速构建的文档编写了cloudbuild.yaml,镜像能正常上传到Artifact Registry,但每次触发新构建时都是从头开始,完全没用到缓存。

我的Dockerfile

# 构建阶段
FROM node:lts-alpine as builder

COPY package.json ./
RUN npm install
RUN mkdir /app-ui
RUN mv ./node_modules ./app-ui
WORKDIR /app-ui
COPY . .
RUN npm run build

# 运行阶段
FROM nginx:alpine

COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf.template
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app-ui/build /usr/share/nginx/html
ENV PORT $PORT
EXPOSE 8080

CMD sh -c "envsubst '\$PORT' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"

我的cloudbuild.yaml

steps:
  - id: pull-cache-image
    name: "gcr.io/cloud-builders/docker"
    entrypoint: "bash"
    args: ["-c", "docker pull ${_IMAGE_NAME} || exit 0"]
  - id: build-container
    name: gcr.io/cloud-builders/docker
    args: ["build", "-t", "${_IMAGE_NAME}", "--cache-from", "${_IMAGE_NAME}", "."]
  - id: push-to-registry
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "${_IMAGE_NAME}"]
  - id: deploy-to-cloud-run
    name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args: [ "run", "deploy", "my-app", "--image", "${_IMAGE_NAME}" ]
images:
  - "${_IMAGE_NAME}"
substitutions:
  _IMAGE_NAME: "europe-west1-docker.pkg.dev/${PROJECT_ID}/my-repository/my-app:prod"
options:
  logging: CLOUD_LOGGING_ONLY
  dynamic_substitutions: true

解决方案

你的问题出在多阶段构建的缓存策略上:当前只指定了最终镜像作为缓存源,但Docker默认只会用它来缓存最后一个阶段,构建阶段(builder)的缓存完全没被利用到。以下是修复步骤:

1. 单独推送构建阶段镜像作为缓存

修改cloudbuild.yaml,在构建时单独标记builder阶段,并推送到Registry,后续构建可以直接拉取这个阶段的缓存:

更新后的cloudbuild.yaml:

steps:
  - id: pull-cache-images
    name: "gcr.io/cloud-builders/docker"
    entrypoint: "bash"
    args: [
      "-c", 
      "docker pull ${_IMAGE_NAME} || exit 0; docker pull ${_BUILDER_IMAGE_NAME} || exit 0"
    ]
  - id: build-container
    name: gcr.io/cloud-builders/docker
    args: [
      "build", 
      "-t", "${_IMAGE_NAME}", 
      "-t", "${_BUILDER_IMAGE_NAME}", 
      "--cache-from", "${_IMAGE_NAME}", 
      "--cache-from", "${_BUILDER_IMAGE_NAME}", 
      "."
    ]
  - id: push-to-registry
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "${_IMAGE_NAME}"]
  - id: push-builder-cache
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "${_BUILDER_IMAGE_NAME}"]
  - id: deploy-to-cloud-run
    name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args: [ "run", "deploy", "my-app", "--image", "${_IMAGE_NAME}" ]
images:
  - "${_IMAGE_NAME}"
  - "${_BUILDER_IMAGE_NAME}"
substitutions:
  _IMAGE_NAME: "europe-west1-docker.pkg.dev/${PROJECT_ID}/my-repository/my-app:prod"
  _BUILDER_IMAGE_NAME: "europe-west1-docker.pkg.dev/${PROJECT_ID}/my-repository/my-app:builder-prod"
options:
  logging: CLOUD_LOGGING_ONLY
  dynamic_substitutions: true

2. 优化Dockerfile的缓存效率

当前Dockerfile的COPY . .在npm install之后,只要项目文件有任何变动,都会触发重新安装依赖。调整顺序,让依赖安装层优先缓存:

更新后的Dockerfile:

# 构建阶段
FROM node:lts-alpine as builder

# 先创建工作目录,避免权限问题
WORKDIR /app-ui
# 先复制package文件,缓存依赖安装层
COPY package.json package-lock.json* ./
RUN npm install
# 再复制其余项目文件
COPY . .
RUN npm run build

# 运行阶段
FROM nginx:alpine

COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf.template
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app-ui/build /usr/share/nginx/html
ENV PORT $PORT
EXPOSE 8080

CMD sh -c "envsubst '\$PORT' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"

3. 验证缓存命中

重新触发构建后,查看Cloud Build日志,如果看到Using cache字样,说明缓存生效了。比如:

Step 3/8 : RUN npm install
---> Using cache
---> abc123456789


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:31:18