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

GitLab CI任务间复用Docker构建缓存的问题排查

GitLab CI/CD 镜像构建问题排查与修复

问题背景

仓库现有.gitlab-ci.yml配置意图通过镜像缓存加速构建,同时在打标签时触发发布构建,但遇到两个问题:

  1. 缓存未生效:即便build阶段无任何变更,构建仍会从头执行
  2. docker-build-tag任务未触发:创建新标签时该任务始终不运行

当前.gitlab-ci.yml配置

# This file is a template, and might need editing before it works on your project.
docker-build-main:
  # Official docker image, develop tag
  image: docker:latest
  stage: build
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker pull "$CI_REGISTRY_IMAGE:develop-depsonly" || true
    - docker build --cache-from "$CI_REGISTRY_IMAGE:develop-depsonly" --target build -t "$CI_REGISTRY_IMAGE:develop-depsonly" .
    - docker push "$CI_REGISTRY_IMAGE:develop-depsonly"
    - docker build -t "$CI_REGISTRY_IMAGE:develop" .
    - docker push "$CI_REGISTRY_IMAGE:develop"
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
      when: never
    - if: $CI_COMMIT_TAG == null
      when: on_success

docker-build-tag:
  # Official docker image, tagged release (also updates latest)
  image: docker:latest
  stage: build
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker pull "$CI_REGISTRY_IMAGE:develop-depsonly" || true
    - docker build --cache-from "$CI_REGISTRY_IMAGE:develop-depsonly" -t "$CI_REGISTRY_IMAGE:develop-depsonly"
    - docker push "$CI_REGISTRY_IMAGE:develop-depsonly"
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" -t "$CI_REGISTRY_IMAGE" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
    - docker push  "$CI_REGISTRY_IMAGE:latest"
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
      when: never
    - if: $CI_COMMIT_TAG
      when: on_success

当前Dockerfile配置

FROM rust:1 as build
RUN cargo install cargo-build-deps

RUN cargo new --bin simply-shorten
WORKDIR /pkg

COPY ./actix/Cargo.toml .
COPY ./actix/Cargo.lock .

RUN cargo build-deps --release

COPY ./actix/src ./src
COPY ./actix/resources ./resources

RUN cargo build --release

FROM frolvlad/alpine-glibc:latest

EXPOSE 2000
RUN apk add sqlite-libs

WORKDIR /opt

COPY --from=build /pkg/target/release/pkg /opt/pkg
COPY --from=build /pkg/resources /opt/resources

CMD ["./pkg"]

问题1:缓存未生效的修复

原因

  • docker-build-tag任务中构建develop-depsonly镜像时,缺少--target build参数,导致没有正确复用缓存阶段
  • Dockerfile中RUN cargo new --bin simply-shorten会生成新文件,破坏后续缓存层的哈希匹配

修复方案

  1. 在docker-build-tag的构建命令中添加--target build参数,确保复用缓存阶段
  2. 移除Dockerfile中不必要的RUN cargo new --bin simply-shorten命令,优化分层顺序,先复制依赖文件再复制源码

修改后的docker-build-tag脚本片段

- docker build --cache-from "$CI_REGISTRY_IMAGE:develop-depsonly" --target build -t "$CI_REGISTRY_IMAGE:develop-depsonly" .

优化后的Dockerfile

FROM rust:1 as build
RUN cargo install cargo-build-deps

WORKDIR /pkg
# 先复制依赖文件,优先复用缓存
COPY ./actix/Cargo.toml ./actix/Cargo.lock ./
RUN cargo build-deps --release

# 再复制源码和资源文件
COPY ./actix/src ./src
COPY ./actix/resources ./resources

RUN cargo build --release

FROM frolvlad/alpine-glibc:latest
EXPOSE 2000
RUN apk add sqlite-libs

WORKDIR /opt
COPY --from=build /pkg/target/release/pkg /opt/pkg
COPY --from=build /pkg/resources /opt/resources

CMD ["./pkg"]

问题2:docker-build-tag任务未触发的修复

原因

创建标签时,CI_COMMIT_BRANCH变量不会被赋值,导致第一条规则if: $CI_COMMIT_BRANCH != "main"直接跳过任务(标签不属于任何分支)

修复方案

修改docker-build-tag的rules,移除分支判断逻辑,确保标签触发时任务正常执行:

修改后的docker-build-tag规则片段

rules:
  - if: $CI_COMMIT_TAG
    when: on_success

如果需要确保标签来自main分支的提交,可以改用CI_COMMIT_REF_NAME变量做判断:

rules:
  - if: $CI_COMMIT_TAG && $CI_COMMIT_REF_NAME == "main"
    when: on_success

最终完整的.gitlab-ci.yml配置

# This file is a template, and might need editing before it works on your project.
docker-build-main:
  # Official docker image, develop tag
  image: docker:latest
  stage: build
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker pull "$CI_REGISTRY_IMAGE:develop-depsonly" || true
    - docker build --cache-from "$CI_REGISTRY_IMAGE:develop-depsonly" --target build -t "$CI_REGISTRY_IMAGE:develop-depsonly" .
    - docker push "$CI_REGISTRY_IMAGE:develop-depsonly"
    - docker build -t "$CI_REGISTRY_IMAGE:develop" .
    - docker push "$CI_REGISTRY_IMAGE:develop"
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
      when: never
    - if: $CI_COMMIT_TAG == null
      when: on_success

docker-build-tag:
  # Official docker image, tagged release (also updates latest)
  image: docker:latest
  stage: build
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker pull "$CI_REGISTRY_IMAGE:develop-depsonly" || true
    - docker build --cache-from "$CI_REGISTRY_IMAGE:develop-depsonly" --target build -t "$CI_REGISTRY_IMAGE:develop-depsonly" .
    - docker push "$CI_REGISTRY_IMAGE:develop-depsonly"
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" -t "$CI_REGISTRY_IMAGE" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
    - docker push  "$CI_REGISTRY_IMAGE:latest"
  rules:
    - if: $CI_COMMIT_TAG
      when: on_success

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:12:51