GitLab Runner如何复用前序作业完整状态实现后续作业全量缓存
GitLab CI作业间环境复用解决方案
核心疑问说明
你无法通过artifacts或cache直接传递prepare-env作业的完整Docker容器状态。GitLab CI中每个作业都会基于指定镜像启动全新的独立容器,前序作业对容器系统层的修改(比如默认路径下的pip安装包)会随着作业容器销毁而消失,只有$CI_PROJECT_DIR工作目录下的文件可以通过artifacts或cache在作业间传递。
可行实现方案
方案1:将依赖安装到工作目录,通过artifacts传递(无需提前构建镜像,最贴合你的需求)
修改pip安装路径,将所有依赖安装到工作目录内,通过artifacts传递该目录,后续作业添加该路径到Python模块搜索路径即可直接使用已安装的依赖,配置示例如下:
stages: - prepare - stage1 - stage2 # 统一所有作业的基础镜像,避免版本差异导致依赖不兼容 image: python:3.7 variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" # 指定依赖安装目录 DEP_DIR: "$CI_PROJECT_DIR/deps" cache: paths: - .cache/pip prepare-env: stage: prepare tags: - docker script: # 将依赖安装到指定的工作目录下 - pip install --target=$DEP_DIR requests - pip list artifacts: # 传递依赖目录给后续所有作业 paths: - $DEP_DIR # 可根据需求设置artifacts保留时间 expire_in: 1 day run-first-job: stage: stage1 tags: - docker script: # 将依赖目录添加到Python模块搜索路径 - export PYTHONPATH="$DEP_DIR:$PYTHONPATH" # 此时可直接导入requests使用 - pip list - python -c "import requests; print(requests.__version__)" run-second-job: stage: stage2 tags: - docker script: - export PYTHONPATH="$DEP_DIR:$PYTHONPATH" - pip list - python -c "import requests; print(requests.__version__)"
方案2:流水线内构建临时Docker镜像(适合有系统级依赖的场景)
如果需要传递的不仅仅是Python依赖,还有apt安装包、系统配置等内容,可在prepare阶段通过Docker-in-Docker构建临时镜像,后续作业直接使用该镜像:
stages: - prepare - stage1 - stage2 variables: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" # 临时镜像名称 TEMP_IMAGE: "ci-temp-python:latest" prepare-env: stage: prepare tags: - docker image: docker:latest services: - docker:dind script: # 编写Dockerfile构建包含依赖的临时镜像 - | cat > Dockerfile << EOF FROM python:3.7 RUN pip install requests EOF - docker build -t $TEMP_IMAGE . # 推送到项目自带的容器镜像仓库,或者本地镜像缓存 - docker push $TEMP_IMAGE run-first-job: stage: stage1 tags: - docker image: $TEMP_IMAGE script: - pip list - python -c "import requests; print(requests.__version__)" run-second-job: stage: stage2 tags: - docker image: $TEMP_IMAGE script: - pip list - python -c "import requests; print(requests.__version__)"
方案3:优化cache配置(适合跨流水线复用依赖)
如果你的依赖不会频繁变更,可以结合cache功能,跨流水线复用依赖包,避免每次运行都重新下载依赖:
- 将pip缓存目录加入cache,就算是新的流水线也可以直接用本地缓存的安装包,无需从PyPI重新下载
- 配合方案1使用可以进一步缩短作业运行时间
内容的提问来源于stack exchange,提问作者Cord Kaldemeyer
相关产品推荐
相关产品推荐

