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

时间:2017-11-16 11:02:12

标签: docker tags docker-compose

根据thisthis GitHub问题,目前在使用docker-compose构建一个或多个服务时,如何为服务的图像提供多个标记没有本机方式图像。

我的用例是构建docker-compose.yml文件中定义的图像,并使用一些自定义标记(例如某些构建编号或日期或类似标记)标记一次,并将其标记为latest

虽然使用docker tag使用普通docker可以轻松实现此目的,docker-compose只允许在image key中设置一个标记。将docker tagdocker-compose一起使用对我来说不是一个选项,因为我想将所有与docker相关的定义保存在docker-compose.yml文件中,而不是将它们复制到我的构建脚本中。

使用docker-compose设置多个标签并且不必首先硬编码/复制图像名称会有什么好处?

4 个答案:

答案 0 :(得分:8)

我提出了几个不同复杂程度的解决方法。它们都依赖于${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解析器(或任何其他语言,如Rubyperl或系统上安装的任何语言)比第一次提到的{{1}更强大因为它不会被评论或编写grep文件的奇怪但有效的方式所迷惑。

在Python中,这可能如下所示:

yml

这种方法的缺点是执行构建的机器必须安装Python3以及PyYAML库。如前所述,此模式可以类似地与Python2或任何其他已安装的编程语言一起使用。

使用某些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 命令

的组合获取图像名称

使用一些本地dockerdocker命令(使用go-templates)的以下方法编写起来有点复杂,但也可以很好地工作。

docker-compose

虽然这种方法没有任何外部依赖性并且比# 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 方法更安全,但是在大型设置上执行以创建和删除容器可能需要几秒钟(尽管通常不是问题)

答案 1 :(得分:8)

如@JordanDeyton所建议,extends不能再以Compose文件格式> 3使用,并且在版本3.4中添加的Extension fields功能可以替代它以实现相同的功能目标。这是一个例子。

version: "3.4"
# Define common behavior
x-ubi-httpd:
  &default-ubi-httpd
  build: ubi-httpd
  # Other settings can also be shared
  image: ubi-httpd:latest

# Define one service by wanted tag
services:
  # Use the extension as is
  ubi-httpd_latest:
    *default-ubi-httpd
  # Override the image tag
  ubi-httpd_major:
    << : *default-ubi-httpd
    image: ubi-httpd:1
  ubi-httpd_minor:
    << : *default-ubi-httpd
    image: ubi-httpd:1.0
  # Using an environment variable defined in a .env file for e.g.
  ubi-httpd_patch:
    << : *default-ubi-httpd
    image: "ubi-httpd:${UBI_HTTPD_PATCH}"

现在可以使用所有定义的标签构建图像

$ docker-compose build
# ...

$ docker images | grep ubi-httpd
# ubi-httpd  1       8cc412411805  3 minutes ago  268MB
# ubi-httpd  1.0     8cc412411805  3 minutes ago  268MB
# ubi-httpd  1.0.1   8cc412411805  3 minutes ago  268MB
# ubi-httpd  latest  8cc412411805  3 minutes ago  268MB

答案 2 :(得分:7)

您还可以采取以下方法:

# build is your actual build spec
build:
  image: myrepo/myimage
  build:
  ...
  ...
# these extend from build and just add new tags statically or from environment variables or 
version_tag:
  extends: build
  image: myrepo/myimage:v1.0
some_other_tag:
  extends: build
  image: myrepo/myimage:${SOME_OTHER_TAG}

然后,您可以运行docker-compose builddocker-compose push,然后构建并推送标记为已成像的正确

答案 3 :(得分:1)

我有一些使用环境变量的简洁解决方案(默认变量值的bash语法,在我的情况下为latest,但您可以使用任何东西),这是我的写信:

version: '3'
services:
  app:
    build: .
    image: myapp-name:${version:-latest}

使用默认标记构建并推送(如果需要推送到注册表),请使用环境变量更改版本,然后再次构建并推送:

docker-compose build
docker-compose push
export version=0.0.1
docker-compose build
docker-compose push