docker - 正确保持docker VSTS/Azure Devops build代理干净但已缓存

标签 docker build kubernetes azure-devops azure-pipelines

我们已经在我们的开发Kubernetes群集中添加了一个dockerized生成代理,我们将其用于构建应用程序作为Azure Devops管道的一部分。我们根据the deprecated Microsoft/vsts-agent-docker on Github.创建了自己的图片
构建代理在Docker(DooD)之外使用Docker在我们的开发集群上创建镜像。
该代理已经运行了好几天,但随后在构建管道中的docker命令上偶尔会出现错误:

Error response from daemon: No such image: fooproject:ci-3284.2 /usr/local/bin/docker failed with return code: 1


我们意识到构建代理正在创建大量未被删除的图像。有大量的图像阻塞了构建代理,并且缺少图像,这可以解释“没有这样的图像”错误消息。
通过使用以下命令在构建管道中添加一个步骤,我们能够使构建代理再次工作:
docker system prune -f -a
但是,这当然会删除我们所有的图像,并且每次都必须从头开始构建它们,这会使我们的构建花费不必要的长时间。
我确定这肯定是一个已解决的问题,但是我无法找到有关处理随时间推移而被堵塞的dockerized build agent的常规策略的任何文档。对docker和kubernetes陌生,我可能根本不知道我在寻找什么。 创建维持清洁和功能性同时维护缓存的dockerized构建代理的最佳实践是什么?
编辑:一些想法:
  • 创建一个构建步骤,该步骤将清除给定管道的所有图像(除了最新镜像以外的所有图像)(尽管这可能仍会阻塞构建服务器)。
  • 运行cron作业,每隔x天删除一次所有镜像(这将导致作业运行后首次运行时生成速度慢,如果使用率很高,仍可能阻塞生成服务器。
  • 每晚清除所有图像,并在工作时间以外运行所有构建。这样,构建将在白天快速运行。但是,大量使用仍然可能阻塞构建服务器。

  • 编辑2:
    我发现有人拿着docker issue on Github似乎在尝试做与我完全相同的事情。他提出了一个解决方案,描述如下:

    I was exactly trying to figure out how to remove "old" images out of my automated build environment without removing my build dependencies. This means I can't just remove by age, because the nodejs image might not change for weeks, while my app builds can be worthless in literally minutes.

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

    That little gem is exactly what I needed. I dropped my repository name in the reference variable (not the most self-explanatory.) Since I tag both the build number and latest the docker image rm command fails on the images I want to keep. I really don't like using daemon errors as a protection mechanism, but its effective.


    为了遵循这些指示,我将latest标记应用于在此过程中生成的所有内容,然后运行docker image ls --filter reference=fooproject如果我尝试删除这些,则会出现以下错误:

    Error response from daemon: conflict: unable to delete b870ec9c12cc (must be forced) - image is referenced in multiple repositories


    这样可以防止最新的文件被删除。但是,这并不是一种干净的方法。一定会有更好的办法?

    最佳答案

    可能您已经找到了解决方案,但是对于其他社区来说,在这里找到答案可能会很有用。
    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
    

    可以结合使用filters子句来确切地获得您所需要的内容:
    (我使用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管道中,可以使您仅将所需的图像保留在本地缓存中,而无需在构建服务器上收集大量垃圾。

    我在这里复制了一个使用comment strajansebastian 提供的方法的好例子:
    #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
    

    关于docker - 正确保持docker VSTS/Azure Devops build代理干净但已缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54670615/

    相关文章:

    docker - 如何从 Windows 10 操作系统为 ARM32 架构构建 docker 容器镜像?

    kubernetes - 在入口资源中找不到端点 “default-http-backend”

    REST 与 gRPC : when should I choose one over the other?

    kubernetes - Kubernetes 中 Pod 的优先级

    django - 如何与Django一起使用Dokku?

    docker 环境下的 Golang revel 框架热重载

    postgresql - Dockerfile ENV变量不被接受

    c++ - 如何使用 Make 构建与一些 C++ 代码混合的 C 项目?

    gradle - 如何获取详细的 Gradle 配置文件数据?

    android - 如何在 Gradle 构建脚本(Android)中定义和使用常量?