Selon this et this GitHub, il n'existe actuellement aucun moyen natif de fournir plusieurs balises pour l'image d'un service lorsque vous utilisez docker-compose
pour créer une ou plusieurs images.
Mon cas d’utilisation serait de construire des images définies dans un fichier docker-compose.yml
et de les taguer une fois avec une balise personnalisée (par exemple, un numéro de compilation ou une date ou similaire) et une fois sous la forme latest
.
Tandis que cela peut être facilement réalisé avec plain docker
en utilisant docker tag , docker-compose
permet uniquement de définir une seule balise dans la clé image . L'utilisation de docker tag
avec docker-compose
n'est pas une option pour moi, car je souhaite conserver toutes mes définitions liées au docker dans le fichier docker-compose.yml
et ne pas les copier dans mon script de construction.
Qu'est-ce qui serait une solution de rechange décente pour définir plusieurs balises avec docker-compose
et sans devoir coder/copier les noms des images au préalable?
Vous pouvez également adopter l'approche suivante:
# 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}
Vous pouvez alors simplement exécuter docker-compose build
et docker-compose Push
et vous construirez et pousserez le bon jeu d'images marquées
J'ai proposé deux solutions de travail d'une complexité différente. Ils s’appuient tous sur l’hypothèse que ${IMAGE_TAG}
stocke l’étiquette personnalisée qui représente, par exemple, un numéro de build et nous voulons marquer les images de tous les services avec cette balise, ainsi qu'avec latest
.
grep
les noms d'image du fichier 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
Cependant, ceci est sujet aux erreurs si quelqu'un ajoute un commentaire dans docker-compose.yml
qui le ferait par exemple. ressembler à # Purpose of this image: do something useful...
.
Utilisez ${IMAGE_TAG}
en tant que variable d'environnement dans votre fichier docker-compose.yml
comme décrit ici dans le premier exemple .
Ensuite, exécutez simplement le processus de construction deux fois, en remplaçant chaque fois ${IMAGE_TAG}
par une valeur différente:
IMAGE_TAG="${IMAGE_TAG}" docker-compose build
IMAGE_TAG=latest docker-compose build
Le deuxième processus de construction devrait être beaucoup plus rapide que le premier, car toutes les couches d'image devraient toujours être mises en cache à partir de la première exécution.
L'inconvénient de cette approche est que la sortie de votre journal sera inondée de deux processus de construction ultérieurs pour chaque service, ce qui rendra plus difficile la recherche d'informations utiles.
De plus, si vous avez dans votre Dockerfile
une commande qui vide toujours le cache de construction (par exemple, une commande ADD
récupérant depuis un emplacement distant avec des en-têtes last-modified
à mise à jour automatique, ajoutant des fichiers constamment mis à jour par un processus externe, etc.), alors la construction supplémentaire pourrait ralentir les choses de manière significative.
docker-compose.yml
avec du code Python en ligneUtiliser un analyseur yaml
réel en Python (ou tout autre langage tel que Ruby
ou Perl
ou tout ce qui est installé sur votre système) est plus robuste que l’approche grep
mentionnée en premier, car il ne sera pas dérouté par des commentaires ou des manières étranges mais valables d’écrire la fichier yml
.
En Python, ceci pourrait ressembler à ceci:
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
L'inconvénient de cette approche est que Python3 doit être installé sur la machine exécutant la construction, ainsi que la bibliothèque PyYAML . Comme déjà mentionné, ce modèle pourrait également être utilisé avec Python2 ou tout autre langage de programmation installé.
docker
L'approche suivante utilisant certaines commandes docker
et docker-compose
natives (à l'aide de go-templates) est un peu plus complexe à écrire mais fonctionne également très bien.
# 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
Bien que cette approche ne comporte pas de dépendances externes et soit plus sûre que la méthode grep
, l’exécution de grandes configurations pour la création et la suppression des conteneurs peut prendre quelques secondes de plus (en général, ce n’est pas un problème).
J'ai quelques solutions simples et propres utilisant des variables d'environnement (syntaxe bash pour la valeur de variable par défaut, dans mon cas, c'est latest
mais vous pouvez utiliser n'importe quoi), voici ma composition:
version: '3'
services:
app:
build: .
image: myapp-name:${version:-latest}
build et Push (si vous avez besoin de Push dans le registre) avec la balise par défaut, modifiez la version à l'aide de la variable d'environnement, puis build et Push à nouveau:
docker-compose build
docker-compose Push
export version=0.0.1
docker-compose build
docker-compose Push