我想出了几种不同复杂度的解决方案。它们都基于这样一个假设:${IMAGE_TAG}
存储着自定义标签,例如构建号码,并且我们希望将所有服务的映像文件都使用此标签以及 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...
,那么这种方法就容易出现错误。
两次构建
在您的docker-compose.yml
文件中使用${IMAGE_TAG}
作为环境变量,如此处第一个示例所述。
然后,只需运行两次构建过程,每次用不同的值替换${IMAGE_TAG}
即可:
IMAGE_TAG="${IMAGE_TAG}" docker-compose build
IMAGE_TAG=latest docker-compose build
第二次构建过程应该比第一次快得多,因为所有的镜像层都应该仍然从第一次运行中被缓存。
这种方法的缺点是它将用两个连续的构建过程淹没您的日志输出,每个单独的服务都会如此,这可能会使搜索有用信息变得更加困难。
此外,如果您的 Dockerfile 中有任何命令总是刷新构建缓存(例如,使用自动更新的 last-modified 标头从远程位置获取的 ADD 命令、添加外部进程不断更新的文件等),那么额外的构建可能会显著减慢速度。
使用一些内联 Python 代码从 docker-compose.yml 文件中解析图像名称
在 Python 中,这可能看起来像这样:
images=$(python3 <<-EOF
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)编写略微复杂,但也很好用。
compose_project_name=myproject.tagging
docker-compose --project-name "${compose_project_name}" up --no-start
images=$(docker-compose --project-name "${compose_project_name}" images -q | xargs docker inspect --format='{{ index .RepoTags 0}}' | cut -d':' -f1)
for image in ${images}
do
docker tag "${image}":"${IMAGE_TAG}" "${image}":latest
done
docker-compose --project-name "${compose_project_name}" down
虽然这种方法没有任何外部依赖,比使用 grep
方法更安全,但在创建和删除容器的大型设置上执行可能需要多几秒钟(尽管通常不是问题)。