我们已经向我们的开发Kubernetes集群添加了一个停靠构建代理,我们使用它作为Azure Devops管道的一部分构建应用程序。我们基于Github上不推荐使用的Microsoft/vsts代理docker创建了自己的映像
构建代理使用Docker外部的Docker(DooD)在我们的开发集群上创建映像
该代理在几天内工作正常,但在构建管道中的docker命令上偶尔会出现错误:
来自守护程序的错误响应:没有这样的映像:fooproject:ci-3284.2
/usr/local/bin/docker失败,返回代码:1
我们意识到构建代理正在创建大量未被删除的图像。有大量的图片阻塞了构建代理,并且缺少了一些图片,这可以解释为什么;“没有这样的形象”;错误消息
通过使用以下命令向构建管道添加步骤,我们能够使构建代理重新工作:
docker系统修剪-f-a
当然,这会删除我们所有的图像,每次都必须从头开始构建,这会导致构建花费不必要的时间
我确信这一定是一个解决了的问题,但我还没有找到任何关于处理停靠的构建代理随着时间的推移变得阻塞的正常策略的文档。作为docker和kubernetes的新手,我可能根本不知道自己在寻找什么在维护缓存的同时,创建保持干净且功能正常的停靠生成代理的最佳做法是什么?
编辑:一些想法:
- 创建一个生成步骤,清除给定管道中除最新映像以外的所有映像(但这仍可能阻塞生成服务器)
- 运行cron作业,每x天删除一次所有映像(这将导致作业运行后第一次生成的速度变慢,并且如果发现大量使用,仍可能阻塞生成服务器)
- 每晚清除所有映像,并在工作时间以外运行所有生成。这样,生成将在白天快速运行。但是大量使用仍可能阻塞生成服务器
编辑2:
我发现有人在Github上遇到docker问题,他似乎正试图做与我完全相同的事情。他提出了一个解决方案,他描述如下:
我正试图弄清楚如何在不删除构建依赖项的情况下从我的自动构建环境中删除“旧”映像。这意味着我不能只按年龄删除,因为nodejs映像可能在几周内不会更改,而我的应用构建可能在几分钟内毫无价值
docker image rm$(docker image ls--filter reference=docker--quiet)这个小小的宝石正是我所需要的。我将我的存储库名称放在引用变量中(不是最自解释的)由于我同时标记了build number和latest,
docker image rm命令在我想要保留的映像上失败。我真的不喜欢使用守护程序错误作为保护机制,但它是有效的
为了遵循这些说明,我将最新的标记应用于该过程中构建的所有内容,然后运行
docker image ls--过滤器引用=fooproject
如果我尝试删除这些,则会出现以下错误:
来自守护程序的错误响应:冲突:无法删除b870ec9c12cc(必须强制)-映像在多个存储库中引用
这会阻止最新的一个被删除。但是这并不是一个干净的方法。一定有更好的方法吗
也许您已经找到了一个解决方案,但是对于社区的其他人来说,在这里找到答案可能会很有用
docker prune的用途有限。创建它是为了解决清除所有本地docker映像的问题。(正如thaJeztah在这里提到的)
要以更精确的方式删除图像,最好将此任务分为两部分:
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--过滤器引用=docker--安静| xargs docker image rm
可以组合筛选器子句以获得您想要的内容:
(我使用Kubernetes主节点作为示例环境)
$docker图像
创建的存储库标记图像ID大小
k8s.gcr.io/kube-proxy v1.14.2 5C24210246B 3个月前82.1MB
k8s.gcr.io/kube-apiserver v1.14.2 5eeff402b659 3个月前210MB
k8s.gcr.io/kube-controller-manager v1.14.2 8be94bdae139 3个月前158MB
k8s.gcr.io/kube-scheduler v1.14.2 ee18f350636d 3个月前81.6MB之前
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 6个月前52.6MB
k8s.gcr.io/coredns 1.3.1 eb516548c180 7个月前4030万字节自
k8s.gcr.io/etcd 3.3.10 2c4adeb21b4f 8个月前258MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 20个月前742kB
$docker images--过滤器“自=eb516548c180”--过滤器“自=ee18f350636d之前”
创建的存储库标记图像ID大小
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 6个月前52.6MB
$docker images--过滤器“自=eb516548c180”--过滤器“reference=quay.io/coreos/flannel”
创建的存储库标记图像ID大小
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 6个月前52.6MB
$docker images--过滤器“自=eb516548c180”--过滤器“参考=quay*/*/*”
创建的存储库标记图像ID大小
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 6个月前52.6MB
$docker images--filter“since=eb516548c180”--filter“reference=*/*/flan*”
创建的存储库标记图像ID大小
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 6个月前52.6MB
如文档中所述,images/images ls过滤器比docker prune过滤器要好得多,后者只支持until子句:
当前支持的筛选器包括:
•悬空(布尔值-真或假)
•标签(标签=<;键>;或标签=<;键>;=<;值>;)
•在(<;图像名称>;[:<;标记>;]、<;图像id>;或<;[email protected]>;)-筛选在给定id或引用之前创建的图像
•自(<;图像名称>;[:<;标记>;],<;图像id>;或<;[email protected]>;)-筛选自给定id或引用后创建的图像
如果需要多个筛选器,则传递多个标志
(例如,——过滤“foo=bar”——过滤“bif=baz”)
您可以使用其他linux cli命令筛选docker图像输出:
grep“something”#仅包括指定的图像
grep-v“something”#排除要保存的图像
排序[-k colN][r][g]|头/尾-nX#以选择X个最旧或最新的图像
将它们组合起来并将结果放入CI/CD管道,这样您就可以在本地缓存中只保留所需的映像,而不会在构建服务器上收集大量垃圾
我在这里复制了一个使用strajansebastian在评论中提供的方法的好例子:
#删除除最后2个版本外的所有版本的示例,用于每种图像
#(图像类型基于存储库值。)
#如果您只想保留上一次构建,请修改为tail-n+2。
#删除死容器
docker容器修剪-f
#为存储库中的每个映像保留最后2个版本
对于` docker images--format“{{.Repository}}”| sort | uniq `;do中的diru
对于` docker images--format“{{.ID};{.Repository}:{{.Tag};{{.CreatedAt}”中的dimr--filter reference=“$diru”| sed-r“s/\s+/~/g”| tail-n+3`;do
img_标签=`echo$dimr | cut-d'”-f2`;
docker rmi$img_标签;
完成;
完成
#清除悬空图像(如果有)
docker图像修剪-f