如何让 gitlab-ci-runner DinD 图像缓存中间图像?
How can I let the gitlab-ci-runner DinD image cache intermediate images?
我有一个从安装texlive-full包开始的Dockerfile,这个文件很大,需要很长时间。如果我 docker build
在本地,安装后创建的中间图像被缓存,后续构建速度很快。
但是,如果我推送到我自己的 GitLab 安装并且 GitLab-CI build runner 启动,这似乎总是从头开始,重新下载 FROM
图像,并执行 apt-重新安装。这对我来说似乎是一个巨大的浪费,所以我想弄清楚如何让 GitLab DinD 图像缓存构建之间的中间图像,到目前为止运气不好。
我已经尝试使用 --cache-dir
和 --docker-cache-dir
作为 gitlab-runner register
命令,但无济于事。
这甚至是 gitlab-runner DinD 图像应该能够做的事情吗?
我的.gitlab-ci.yml
:
build_job:
script:
- docker build --tag=example/foo .
我的Dockerfile
:
FROM php:5.6-fpm
MAINTAINER Roel Harbers <roel.harbers@example.com>
RUN apt-get update && apt-get install -qq -y --fix-missing --no-install-recommends texlive-full
RUN echo Do other stuff that has to be done every build.
我使用 GitLab CE 8.4.0 和 gitlab/gitlab-runner:最新作为跑步者,开始为
docker run -d --name gitlab-runner --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/local/gitlab-ci-runner/config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest \
; \
跑步者使用以下方式注册:
docker exec -it gitlab-runner gitlab-runner register \
--name foo.example.com \
--url https://gitlab.example.com/ci \
--cache-dir /cache/build/ \
--executor docker \
--docker-image gitlab/dind:latest \
--docker-privileged \
--docker-disable-cache false \
--docker-cache-dir /cache/docker/ \
; \
这将创建以下 config.toml
:
concurrent = 1
[[runners]]
name = "foo.example.com"
url = "https://gitlab.example.com/ci"
token = "foobarsldkflkdsjfkldsj"
tls-ca-file = ""
executor = "docker"
cache_dir = "/cache/build/"
[runners.docker]
image = "gitlab/dind:latest"
privileged = true
disable_cache = false
volumes = ["/cache"]
cache_dir = "/cache/docker/"
(我尝试了 cache_dir
、docker_cache_dir
和 disable_cache
的不同值,结果都一样:没有任何缓存)
我想您的问题没有简单的答案。在添加一些细节之前,我强烈建议阅读 DinD 维护者的 this blog article,最初名为 "do not use Docker in Docker for CI".
您可能会尝试将 /var/lib/docker
声明为 GitLab 运行程序的卷。但请注意,根据您的文件系统驱动程序,您可能会在主机上的 AUFS 文件系统上的容器中使用 AUFS,这很可能会导致问题。
我建议您创建一个 单独的 Docker-VM,仅用于运行器和绑定挂载 docker.sock
从 VM 到你的 runner-container。
我们将此设置与 GitLab 一起使用并取得了巨大成功(在大约 12 个月内构建了超过 27.000 个版本)。
大家可以看看我们的runner with docker-compose
support,其实是基于GitLab的runner的shell-executor
目前您无法在 GitLab Docker-in-Docker 中缓存中间层。虽然有计划添加(在下面的 link 中提到)。你今天可以做的来加速你的 DinD 构建是使用覆盖文件系统。为此,您需要 运行 一个 liunx 内核 >=3.18 并确保加载覆盖内核模块。然后你在你的gitlab中设置这个变量-ci.yml:
variables:
DOCKER_DRIVER: overlay
有关更多信息,请参阅此问题,特别是关于 "The state of optimising Docker Builds!" 的评论,请参阅 "Using docker executor with dind" 部分。
https://gitlab.com/gitlab-org/gitlab-ce/issues/17861#note_12991518
对于不经常更改的构建依赖项,您可以使用 gitlab 图像注册表进行手动缓存。
在 CI 脚本中,您不会明确调用 docker build
而是将其包装在 shell 脚本中
# cat build_dependencies.sh
registry=registry.example.com
project=group/project
imagebase=$registry/$project/linux
docker pull $imagebase/devbase:1.0
if [ $? -ne 0 ]; then
docker build -f devbase.dockerfile -t $imagebase/devbase:1.0 .
docker push $imagebase/devbase:1.0
fi
...
并在您的 CI
中调用该脚本
...
script:
- ./build_dependencies.sh
这样做的缺点是,当您的 devbase.dockerfile
更新时,CI 不会注意到这一点,因此您需要强制构建和推送新图像。因此,对于动态更改的图像,这效果不佳,但对于您的用例,这似乎是一种可行的方法。
我有一个从安装texlive-full包开始的Dockerfile,这个文件很大,需要很长时间。如果我 docker build
在本地,安装后创建的中间图像被缓存,后续构建速度很快。
但是,如果我推送到我自己的 GitLab 安装并且 GitLab-CI build runner 启动,这似乎总是从头开始,重新下载 FROM
图像,并执行 apt-重新安装。这对我来说似乎是一个巨大的浪费,所以我想弄清楚如何让 GitLab DinD 图像缓存构建之间的中间图像,到目前为止运气不好。
我已经尝试使用 --cache-dir
和 --docker-cache-dir
作为 gitlab-runner register
命令,但无济于事。
这甚至是 gitlab-runner DinD 图像应该能够做的事情吗?
我的.gitlab-ci.yml
:
build_job:
script:
- docker build --tag=example/foo .
我的Dockerfile
:
FROM php:5.6-fpm
MAINTAINER Roel Harbers <roel.harbers@example.com>
RUN apt-get update && apt-get install -qq -y --fix-missing --no-install-recommends texlive-full
RUN echo Do other stuff that has to be done every build.
我使用 GitLab CE 8.4.0 和 gitlab/gitlab-runner:最新作为跑步者,开始为
docker run -d --name gitlab-runner --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/local/gitlab-ci-runner/config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest \
; \
跑步者使用以下方式注册:
docker exec -it gitlab-runner gitlab-runner register \
--name foo.example.com \
--url https://gitlab.example.com/ci \
--cache-dir /cache/build/ \
--executor docker \
--docker-image gitlab/dind:latest \
--docker-privileged \
--docker-disable-cache false \
--docker-cache-dir /cache/docker/ \
; \
这将创建以下 config.toml
:
concurrent = 1
[[runners]]
name = "foo.example.com"
url = "https://gitlab.example.com/ci"
token = "foobarsldkflkdsjfkldsj"
tls-ca-file = ""
executor = "docker"
cache_dir = "/cache/build/"
[runners.docker]
image = "gitlab/dind:latest"
privileged = true
disable_cache = false
volumes = ["/cache"]
cache_dir = "/cache/docker/"
(我尝试了 cache_dir
、docker_cache_dir
和 disable_cache
的不同值,结果都一样:没有任何缓存)
我想您的问题没有简单的答案。在添加一些细节之前,我强烈建议阅读 DinD 维护者的 this blog article,最初名为 "do not use Docker in Docker for CI".
您可能会尝试将 /var/lib/docker
声明为 GitLab 运行程序的卷。但请注意,根据您的文件系统驱动程序,您可能会在主机上的 AUFS 文件系统上的容器中使用 AUFS,这很可能会导致问题。
我建议您创建一个 单独的 Docker-VM,仅用于运行器和绑定挂载 docker.sock
从 VM 到你的 runner-container。
我们将此设置与 GitLab 一起使用并取得了巨大成功(在大约 12 个月内构建了超过 27.000 个版本)。
大家可以看看我们的runner with docker-compose
support,其实是基于GitLab的runner的shell-executor
目前您无法在 GitLab Docker-in-Docker 中缓存中间层。虽然有计划添加(在下面的 link 中提到)。你今天可以做的来加速你的 DinD 构建是使用覆盖文件系统。为此,您需要 运行 一个 liunx 内核 >=3.18 并确保加载覆盖内核模块。然后你在你的gitlab中设置这个变量-ci.yml:
variables:
DOCKER_DRIVER: overlay
有关更多信息,请参阅此问题,特别是关于 "The state of optimising Docker Builds!" 的评论,请参阅 "Using docker executor with dind" 部分。
https://gitlab.com/gitlab-org/gitlab-ce/issues/17861#note_12991518
对于不经常更改的构建依赖项,您可以使用 gitlab 图像注册表进行手动缓存。
在 CI 脚本中,您不会明确调用 docker build
而是将其包装在 shell 脚本中
# cat build_dependencies.sh
registry=registry.example.com
project=group/project
imagebase=$registry/$project/linux
docker pull $imagebase/devbase:1.0
if [ $? -ne 0 ]; then
docker build -f devbase.dockerfile -t $imagebase/devbase:1.0 .
docker push $imagebase/devbase:1.0
fi
...
并在您的 CI
中调用该脚本 ...
script:
- ./build_dependencies.sh
这样做的缺点是,当您的 devbase.dockerfile
更新时,CI 不会注意到这一点,因此您需要强制构建和推送新图像。因此,对于动态更改的图像,这效果不佳,但对于您的用例,这似乎是一种可行的方法。