缓存 gitlab-ci 的虚拟环境

问题描述 投票:0回答:4

我使用 Gitlab CI 脚本缓存了 Pip 包,所以这不是问题。

现在我也想赶一个Conda虚拟环境,因为它减少了设置环境的时间。

我缓存了一个虚拟环境。不幸的是,最后需要很长时间才能缓存所有 venv 文件。

我尝试仅缓存

$CI_PROJECT_DIR/myenv/lib/python3.6/site-packages
文件夹,它似乎减少了管道的运行时间。

我的问题是:我做得正确吗?

脚本如下:

gitlab-ci.yml

image: continuumio/miniconda3:latest

cache:
  paths:
    - .pip
    - ls -l $CI_PROJECT_DIR/myvenv/lib/python3.6/site-packages
    - $CI_PROJECT_DIR/myvenv/lib/python3.6/site-packages

before_script:
  - chmod +x gitlab-ci.sh
  - ./gitlab-ci.sh

stages:
  - test

test:
  stage: test
  script:
    - python eval.py

gitlab-ci.sh

#!/usr/bin/env bash
ENV_NAME=myenv
ENV_REQUIREMENTS=requirements.txt

if [ ! -d $ENV_NAME ]; then
    echo "Environment $ENV_NAME does not exist. Creating it now!"
    conda create --path --prefix "$CI_PROJECT_DIR/$ENV_NAME"
fi

echo "Activating environment: $CI_PROJECT_DIR/$ENV_NAME"
source activate "$CI_PROJECT_DIR/$ENV_NAME"

echo "Installing PIP"
conda install -y pip

echo "PIP: installing required packages"
echo `which pip`
pip --cache-dir=.pip install -r "$ENV_REQUIREMENTS"
python-3.x caching pip conda gitlab-ci
4个回答
8
投票

在构建之间重用 pip 缓存是一个非常好的主意,但对 virtualenvs 执行相同的操作是一个非常糟糕的主意。

这是因为 virtualenv 很容易变得混乱,而你在运行时无法真正检测到。这种情况不仅会发生,而且发生的频率比您想象的要高,因此请避免这种情况。

PS。来自经历过惨痛教训的人的建议。


5
投票

我没有足够的代表来评论 @sorin 的答案,但我们现在在当前的 GitLab (14.6) 上遇到了同样的问题。

我们有四个作业,都使用相同的基础 Docker 镜像。其一,我们设置一个 virtualenv,然后缓存它;其他 3 个作业拉取缓存,激活 venv,然后尝试使用它。这 3 个作业经常失败,因为它们无法找到正确的 python 或从激活的 venv 加载特定模块。

virtualenv
的问题是(至少从Python 3.3中的venv模块开始)virtualenvs是不可重定位的。
activate
脚本在
VIRTUAL_ENV
变量中包含 virtualenv 的绝对路径。默认情况下,GitLab 运行程序将唯一的运行程序令牌作为 build 目录的一部分包含在内,然后该目录将成为该
VIRTUAL_ENV
变量的一部分。因此,如果您在一个运行器上缓存 virtualenv,然后尝试在另一个运行器上使用它,则会失败,因为路径不匹配。
activate
甚至不会警告您
VIRTUAL_ENV
路径不存在。

如果您有一个 GitLab 运行程序,那么您可能没问题。如果没有,您可以自己编写脚本来更新 virtualenv,这可能会或可能不会很好地工作(请参阅我可以移动 virtualenv 吗?)。或者做安全的事情,在每项工作中重新创造 venv;至少你可以不用缓存pip缓存。


4
投票

我们成功使用了文档中概述的方法https://docs.gitlab.com/ee/ci/caching/#caching-python-dependency

# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
#
# If you want to also cache the installed packages, you have to install
# them in a virtualenv and cache it as well.
cache:
  paths:
    - .cache/pip
    - venv/

可能还缺少其他东西,但你的第一遍可能会错过:

  • 当减小整个
    .../venv/
    目录树的大小时,您可能需要
    .../venv/bin
    ,因为这是找到正确的 python 版本所必需的;使用命令
    activate
     
    venv
    ing 
    which -a python3
  • 后在本地查看此内容
  • 如果将再次使用 pip(例如稍后在构建中通过某些 make 配方),您需要移动
    pip
    缓存,如上所示。

0
投票

在我们使用 Kubernetes 运行器的项目中,我们使用以下方法:

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

cache:
  paths:
    - .cache/pip
    - venv

.python-base:
  image: "some-image-with-python3"
  before_script:
    - test -f venv/bin/python || python3 -m venv venv
    - source venv/bin/activate
    - pip install --upgrade pip
    - pip install -r requirements.txt

some-python-job:
  extends: .python-base

k8s 运行器上的工作目录始终相同,因此引用不存在的目录没有问题。通过验证是否可以解析到 python 的链接,仅当 python 版本更改或不存在 venv 时才会创建新的 venv。

不确定还有什么其他事情会搞砸(参见sorin的回答),但对我们来说,到目前为止,这非常有效。我们主要将它用于作为构建本身的一部分运行的 python 脚本,这确实节省了时间。也许在使用它来生成其他地方使用的 python 包时更加谨慎是明智的。

© www.soinside.com 2019 - 2024. All rights reserved.