Construire des images dépendantes
Pour réduire le temps de push/pull et le poids des images, une pratique courante pour les applications Compose est de faire en sorte que les services partagent le plus possible de couches de base. Vous sélectionnerez généralement la même image de base du système d'exploitation pour tous les services. Mais vous pouvez également aller plus loin en partageant des couches d'image lorsque vos images partagent les mêmes paquets système. Le défi à relever est alors d'éviter de répéter exactement la même instruction Dockerfile dans tous les services.
Pour illustration, cette page suppose que vous voulez que tous vos services soient construits avec une image de base alpine
et installer le paquet système openssl
.
Dockerfile multi-étapes
L'approche recommandée est de regrouper la déclaration partagée dans un seul Dockerfile, et d'utiliser les fonctionnalités multi-étapes pour que les images de service soient construites à partir de cette déclaration partagée.
Dockerfile :
FROM alpine as base
RUN /bin/sh -c apk add --update --no-cache openssl
FROM base as service_a
# construire le service a
...
FROM base as service_b
# construire le service b
...
Fichier Compose :
services:
a:
build:
target: service_a
b:
build:
target: service_b
Utiliser l'image d'un autre service comme image de base
Un modèle populaire est de réutiliser l'image d'un service comme image de base dans un autre service. Comme Compose n'analyse pas le Dockerfile, il ne peut pas détecter automatiquement cette dépendance entre les services pour ordonner correctement l'exécution de la construction.
a.Dockerfile :
FROM alpine
RUN /bin/sh -c apk add --update --no-cache openssl
b.Dockerfile :
FROM service_a
# construire le service b
Fichier Compose :
services:
a:
image: service_a
build:
dockerfile: a.Dockerfile
b:
image: service_b
build:
dockerfile: b.Dockerfile
L'ancien Docker Compose v1 construisait les images séquentiellement, ce qui rendait ce modèle utilisable prêt à l'emploi. Compose v2 utilise BuildKit pour optimiser les constructions et construire les images en parallèle et nécessite une déclaration explicite.
L'approche recommandée est de déclarer l'image de base dépendante comme un contexte de construction supplémentaire :
Fichier Compose :
services:
a:
image: service_a
build:
dockerfile: a.Dockerfile
b:
image: service_b
build:
dockerfile: b.Dockerfile
additional_contexts:
# `FROM service_a` sera résolu comme une dépendance sur le service "a" qui doit être construit en premier
service_a: "service:a"
Avec l'attribut additional_contexts
, vous pouvez référencer une image construite par un autre service sans avoir besoin de la nommer explicitement :
b.Dockerfile :
FROM base_image
# `base_image` ne résout pas vers une image réelle. Ceci est utilisé pour pointer vers un contexte supplémentaire nommé
# construire le service b
Fichier Compose :
services:
a:
build:
dockerfile: a.Dockerfile
# l'image construite sera taguée <nom_projet>_a
b:
build:
dockerfile: b.Dockerfile
additional_contexts:
# `FROM base_image` sera résolu comme une dépendance sur le service "a" qui doit être construit en premier
base_image: "service:a"
Construire avec Bake
Utiliser Bake vous permet de passer la définition de construction complète pour tous les services et d'orchestrer l'exécution de la construction de la manière la plus efficace.
Pour activer cette fonctionnalité, exécutez Compose avec la variable COMPOSE_BAKE=true
définie dans votre environnement.
$ COMPOSE_BAKE=true docker compose build
[+] Building 0.0s (0/1)
=> [internal] load local bake definitions 0.0s
...
[+] Building 2/2 manifest list sha256:4bd2e88a262a02ddef525c381a5bdb08c83 0.0s
✔ service_b Built 0.7s
✔ service_a Built
Bake peut également être sélectionné comme constructeur par défaut en éditant votre fichier de configuration $HOME/.docker/config.json
:
{
...
"plugins": {
"compose": {
"build": "bake"
}
}
...
}