如何使用docker-compose使用多个图像标签

根据这个和这个 GitHub的问题,当使用docker-compose构build一个或多个图像时,如何为服务的图像提供多个标记,目前没有原生的方法。

我的用例是构builddocker-compose.yml文件中定义的图像,并使用一些自定义标签(例如一些内部版本号,date或类似标签)标记一次,最后一次标记。

虽然使用docker标签的普通docker可以轻松实现,但docker-compose只允许在image key中设置一个标签。 使用docker tagdocker-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中使用真正的yamlparsing器(或任何其他语言,如Rubyperl或任何安装在您系统上的语言)比第一个提到的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命令的组合获取图像名称

下面的方法使用一些本地的dockerdocker-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和移除容器可能需要几秒钟的时间(通常不是问题)。