如何将 gitlab 作业令牌传递到 docker 构建而不导致缓存丢失?

dap*_*azz 6 gitlab docker

我们正在使用 gitlab 部署中内置的 PyPI 存储库来与多个内部项目共享我们的内部包。当我们构建 Docker 镜像时,我们需要安装这些软件包作为镜像创建的一部分。然而,我们用来访问 gitlab PyPI 存储库的gitlab CI 令牌是一次性令牌,因此每次运行构建时都是不同的。

我们的 Dockerfile 的开头是这样的:

FROM python:3.9

WORKDIR /project

COPY poetry.lock pyproject.toml
RUN pip install poetry

ARG CI_JOB_TOKEN
RUN poetry config http-basic.gitlab-pypi-repo gitlab-ci-token ${CI_JOB_TOKEN}
RUN poetry install --no-interaction
Run Code Online (Sandbox Code Playgroud)

现在因为我们正在使用诗歌并且版本被锁定poetry.lock,当我们到达诗歌步骤时,我们不需要重新安装诗歌,除非文件poetry.lock已更改,但由于总是CI_JOB_TOKEN不同,我们总是会错过缓存并必须重建诗歌和下游的一切(实际上这是大部分工作所在的地方)。

那么有没有一种方法可以传递CI_JOB_TOKEN到 docker 构建中,但为了缓存的目的而被忽略呢?或者也许还有另一种方法可以实现这一目标?

syt*_*ech 3

使用构建秘密(需要构建套件)

--mount您可以使用指令的参数在构建时安装机密RUN。假设 dockerfile 中有以下内容:

# ...
RUN --mount=type=secret,id=mysecret echo "$(cat /run/secrets/mysecret)" > .foo
RUN echo "another layer" > .bar
Run Code Online (Sandbox Code Playgroud)

然后您可以使用该标志将秘密传递到构建中--secret

在第一次运行时,您将看到RUN执行的指令,如果您要检查该.foo文件,它将包含秘密(因为我们将其回显到命令中的文件RUN- 实际上,这可能是您的诗歌配置,对于例子)。

# ...
RUN --mount=type=secret,id=mysecret echo "$(cat /run/secrets/mysecret)" > .foo
RUN echo "another layer" > .bar
Run Code Online (Sandbox Code Playgroud)

即使您的秘密发生变化,在后续运行中,您也会看到相关层仍然保留缓存:

$ echo -n supersecret > ../secret.txt
$ docker build --secret id=mysecret,src=../secret.txt -t test .
# ...
 => [3/4] RUN --mount=type=secret,id=mysecret echo "$(cat /run/secrets/mysecret)" > .foo                                                0.2s
 => [4/4] RUN echo "another layer" > .bar                                                                                                         0.4s
# ...
Run Code Online (Sandbox Code Playgroud)

当然,因为 RUN 指令已被缓存,所以您会在.foo生成的构建中看到旧的秘密值。


作为单独的注释,您应该知道您的poetry config命令正在写入磁盘。这意味着您的秘密将包含在生成的图像层中,从安全角度来看这可能并不理想。