我想出了几个不同复杂度的变通办法。它们都依赖于${IMAGE_TAG} 存储代表例如的自定义标签的假设。一个版本号。我们想用这个标签以及latest来标记所有服务的图像。
grep docker-compose.yml 文件中的图像名称
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...。
构建两次
使用${IMAGE_TAG} 作为docker-compose.yml 文件中的环境变量,如here in the first example 所述。
然后,只需运行构建过程两次,每次将 ${IMAGE_TAG} 替换为不同的值:
IMAGE_TAG="${IMAGE_TAG}" docker-compose build
IMAGE_TAG=latest docker-compose build
第二个构建过程应该比第一个快得多,因为所有图像层仍然应该从第一次运行开始缓存。
这种方法的缺点是它会为每个单独的服务使用两个后续构建过程来淹没您的日志输出,这可能会使通过它搜索有用的东西变得更加困难。
此外,如果您的 Dockerfile 中有任何命令总是刷新构建缓存(例如,ADD 命令从远程位置获取并自动更新 last-modified 标头,添加由外部进程等),那么额外的构建可能会显着减慢速度。
使用一些内联 Python 代码从 docker-compose.yml 文件中解析图像名称
在 Python 中使用真正的 yaml 解析器(或任何其他语言,例如 Ruby 或 perl 或您系统上安装的任何其他语言)比第一次提到的 grep 方法更强大,因为它不会得到被 cmets 或编写 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
这种方法的缺点是执行构建的机器必须安装 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 方法更安全,但在创建和删除容器的大型设置上执行可能需要几秒钟的时间(但通常不是问题)。