【问题标题】:Correctly keeping docker VSTS / Azure Devops build agent clean yet cached正确保持 docker VSTS / Azure Devops 构建代理干净但缓存
【发布时间】:2019-02-13 12:49:06
【问题描述】:

我们在开发 Kubernetes 集群中添加了一个 dockerised 构建代理,我们使用它来构建我们的应用程序,作为 Azure Devops 管道的一部分。我们基于the deprecated Microsoft/vsts-agent-docker on Github.创建了自己的镜像

构建代理使用 Docker 外部的 Docker (DooD) 在我们的开发集群上创建映像。

这个代理运行了几天,但在我们构建管道中的 docker 命令上偶尔会出现错误:

来自守护进程的错误响应:没有这样的图像:fooproject:ci-3284.2 /usr/local/bin/docker 失败,返回码:1

我们意识到构建代理正在创建大量没有被删除的图像。有大量图像阻塞了构建代理并且缺少图像,这可以解释“没有这样的图像”错误消息。

通过使用以下命令向我们的构建管道添加一个步骤,我们能够让我们的构建代理再次工作:

docker system prune -f -a

但这当然会删除我们所有的图像,并且每次都必须从头开始构建它们,这导致我们的构建花费了不必要的长时间。

我确定这一定是一个已解决的问题,但我无法找到任何有关处理 dockerised 构建代理随着时间的推移而阻塞的正常策略的文档。作为 docker 和 kubernetes 的新手,我可能根本不知道自己在寻找什么。 在保持缓存的同时,创建一个保持清洁和功能的 dockerised 构建代理的最佳做法是什么?

编辑:一些想法:

  • 创建一个构建步骤,清除给定管道的除最新映像之外的所有映像(但这可能仍会阻塞构建服务器)。
  • 运行一个 cron 作业,每 x 天删除一次所有映像(这会导致作业运行后的第一次构建速度变慢,并且如果看到大量使用仍会阻塞构建服务器。
  • 每晚清除所有映像并在工作时间之外运行所有构建。这样构建将在白天快速运行。但是,大量使用仍会阻塞构建服务器。

编辑 2:

我发现某人的docker issue on Github 似乎正在尝试做与我完全相同的事情。他想出了一个解决方案,他描述如下:

我只是想弄清楚如何从我的自动构建环境中删除“旧”图像而不删除我的构建依赖项。这意味着我不能只按年龄删除,因为 nodejs 图像可能在数周内都不会改变,而我的应用程序构建可能在几分钟内就毫无价值。

docker image rm $(docker image ls --filter reference=docker --quiet)

那个小宝石正是我需要的。我将 repository name 放在 reference 变量中(不是最不言自明的。)因为我标记了内部版本号和 latest @ 987654325@ 命令在我要保留的图像上失败。我真的不喜欢使用守护进程错误作为保护机制,但它很有效。

尝试遵循这些指示,我已将latest 标记应用于过程中构建的所有内容,然后运行

docker image ls --filter reference=fooproject

如果我尝试删除这些,我会收到以下错误:

来自守护程序的错误响应:冲突:无法删除 b870ec9c12cc(必须强制)- 图像在多个存储库中引用

这样可以防止删除最新的。然而,这并不完全是一种干净的方式。一定有更好的办法吗?

【问题讨论】:

  • VAS 提供的解决方案对您有用吗?
  • 你找到干净的解决方案了吗?

标签: docker build kubernetes azure-devops azure-pipelines


【解决方案1】:

您可能已经找到了解决方案,但在这里找到答案可能对社区的其他人有用。

docker prune 的用途有限。创建它是为了解决清理所有本地 Docker 映像的问题。 (正如 thaJeztah here 提到的)

要以更精确的方式删除图像,最好将此任务分为两部分: 1.选择/过滤要删除的图像 2.删除选中图片列表

例如:

docker image rm $(docker image ls --filter reference=docker --quiet)
docker image rm $(sudo docker image ls | grep 1.14 | awk '{print $3}')
docker image ls --filter reference=docker --quiet | xargs docker image rm

可以组合过滤器子句以获得您想要的内容:
(我以 Kubernetes 主节点为例环境)

$ docker images

REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
k8s.gcr.io/kube-proxy                v1.14.2             5c24210246bb        3 months ago        82.1MB
k8s.gcr.io/kube-apiserver            v1.14.2             5eeff402b659        3 months ago        210MB
k8s.gcr.io/kube-controller-manager   v1.14.2             8be94bdae139        3 months ago        158MB
k8s.gcr.io/kube-scheduler            v1.14.2             ee18f350636d        3 months ago        81.6MB  # before
quay.io/coreos/flannel               v0.11.0-amd64       ff281650a721        6 months ago        52.6MB
k8s.gcr.io/coredns                   1.3.1               eb516548c180        7 months ago        40.3MB  # since
k8s.gcr.io/etcd                      3.3.10              2c4adeb21b4f        8 months ago        258MB
k8s.gcr.io/pause                     3.1                 da86e6ba6ca1        20 months ago       742kB

$ docker images --filter "since=eb516548c180" --filter "before=ee18f350636d" 

REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
quay.io/coreos/flannel   v0.11.0-amd64       ff281650a721        6 months ago        52.6MB

$ docker images --filter "since=eb516548c180" --filter "reference=quay.io/coreos/flannel" 
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
quay.io/coreos/flannel   v0.11.0-amd64       ff281650a721        6 months ago        52.6MB

$ docker images --filter "since=eb516548c180" --filter "reference=quay*/*/*" 
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
quay.io/coreos/flannel   v0.11.0-amd64       ff281650a721        6 months ago        52.6MB

$ docker images --filter "since=eb516548c180" --filter "reference=*/*/flan*" 
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
quay.io/coreos/flannel   v0.11.0-amd64       ff281650a721        6 months ago        52.6MB

正如documentation 中提到的,images / image ls 过滤器比 docker prune 过滤器好得多,后者仅支持 until 子句:

The currently supported filters are:
• dangling (boolean - true or false)  
• label (label=<key> or label=<key>=<value>)  
• before (<image-name>[:<tag>], <image id> or <image@digest>) - filter images created before given id or references
• since (<image-name>[:<tag>], <image id> or <image@digest>) - filter images created since given id or references

如果您需要多个过滤器,则传递多个标志 (例如,--filter "foo=bar" --filter "bif=baz"

您可以使用其他linux cli命令过滤docker images输出:

grep "something"      # to include only specified images
grep -v "something"   # to exclude images you want to save
sort [-k colN] [-r] [-g]] | head/tail -nX  # to select X oldest or newest images

结合它们并将结果放入 CI/CD 管道,您可以只将所需的图像留在本地缓存中,而不会在构建服务器上收集大量垃圾。

我在这里复制了一个使用 strajansebastiancomment 中提供的方法的好例子:

#example of deleting all builds except last 2 for each kind of image 
#(the image kind is based on the Repository value.)

#If you want to preserve just last build modify to tail -n+2.

# delete dead containers
docker container prune -f

# keep last 2 builds for each image from the repository
for diru in `docker images --format "{{.Repository}}" | sort | uniq`; do
    for dimr in `docker images --format "{{.ID}};{{.Repository}}:{{.Tag}};'{{.CreatedAt}}'" --filter reference="$diru" | sed -r "s/\s+/~/g" | tail -n+3`; do 
        img_tag=`echo $dimr | cut -d";" -f2`; 
        docker rmi $img_tag;
    done;
done

# clean dangling images if any
docker image prune -f

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    相关资源
    最近更新 更多