如何使用docker-compose使用多个图像标签
根据这个和这个 GitHub的问题,当使用docker-compose
构build一个或多个图像时,如何为服务的图像提供多个标记,目前没有原生的方法。
我的用例是构builddocker-compose.yml
文件中定义的图像,并使用一些自定义标签(例如一些内部版本号,date或类似标签)标记一次,最后一次标记。
虽然使用docker标签的普通docker
可以轻松实现,但docker-compose
只允许在image key中设置一个标签。 使用docker tag
与docker-compose
一起是不是我的select,因为我想保留所有我的docker相关的定义在docker-compose.yml
文件中,而不是复制到我的构build脚本。
用docker-compose
实现多个标签的设置,而不必先硬编码/复制图片名称,这将是一个体面的解决scheme。
我想出了一些复杂度不同的解决方法。 他们都依赖于${IMAGE_TAG}
存储表示例如构build号的定制标记的假设。 我们想用这个标签和latest
标签标记所有服务的图片。
从docker-compose.yml
文件中grep
图像名称
images=$(cat docker-compose.yml | grep 'image: ' | cut -d':' -f 2 | tr -d '"') for image in $images do docker tag "${image}":"${IMAGE_TAG}" "${image}":latest done
但是,如果有人在docker-compose.yml
添加了一条评论,那么这很容易出错,例如# Purpose of this image: do something useful...
。
build造两次
使用${IMAGE_TAG}
作为docker-compose.yml
文件中的环境variables,如第一个示例中所述 。
然后,只需运行构build过程两次,每次用不同的值replace${IMAGE_TAG}
:
IMAGE_TAG="${IMAGE_TAG}" docker-compose build IMAGE_TAG=latest docker-compose build
第二个构build过程应该比第一个构build过程快得多,因为所有图像层都应该从第一个运行caching。
这种方法的缺点是,它会洪泛您的日志输出与每个单一服务的两个后续的构build过程,可能会使更难search一些有用的东西。
另外,如果在你的Dockerfile
有任何一个总是刷新构buildcaching的命令(例如,一个ADD
命令从远程位置获取并自动更新last-modified
标题,添加由外部进程不断更新的文件等)额外的构build可能会显着减慢速度。
用一些内嵌的Python代码parsingdocker-compose.yml
文件中的图像名称
在Python中使用真正的yaml
parsing器(或任何其他语言,如Ruby
或perl
或任何安装在您系统上的语言)比第一个提到的grep
方法更健壮,因为它不会被评论或奇怪而有效的写法yml
文件。
在Python中,这可能看起来像这样:
images=$(python3 <<-EOF # make sure below to indent with tabs, not spaces; or omit the "-" before "EOF" and use no indention at all import yaml content = yaml.load(open("docker-compose.build.yml")) services = content["services"].values() image_names = (service["image"].split(":")[0] for service in services) print("\n".join(image_names)) EOF ) for image in ${images} do docker tag ${image}:${IMAGE_TAG} ${image}:latest done
这种方法的缺点是执行构build的机器必须安装Python3以及PyYAML库。 如前所述,这种模式可以类似地用于Python2或其他安装的编程语言。
使用一些docker
命令的组合获取图像名称
下面的方法使用一些本地的docker
和docker-compose
命令(使用go-templates)写起来有点复杂,但也很好地工作。
# this should be set to something unique in order to avoid conflicts with other running docker-compose projects compose_project_name=myproject.tagging # create containers for all services without starting them docker-compose --project-name "${compose_project_name}" up --no-start # get image names without tags for all started containers images=$(docker-compose --project-name "${compose_project_name}" images -q | xargs docker inspect --format='{{ index .RepoTags 0}}' | cut -d':' -f1) # iterate over images and re-tag for image in ${images} do docker tag "${image}":"${IMAGE_TAG}" "${image}":latest done # clean-up created containers again docker-compose --project-name "${compose_project_name}" down
虽然这种方法没有任何外部依赖,并且比grep
方法更安全,但是在大型设置上执行创build和移除容器可能需要几秒钟的时间(通常不是问题)。