Contexte de build
Les commandes docker build
et docker buildx build
construisent des images Docker à partir
d'un
Dockerfile et d'un contexte.
Qu'est-ce qu'un contexte de build ?
Le contexte de build est l'ensemble des fichiers auxquels votre build peut accéder. L'argument positionnel que vous passez à la commande build spécifie le contexte que vous voulez utiliser pour le build :
$ docker build [OPTIONS] PATH | URL | -
^^^^^^^^^^^^^^
Vous pouvez passer n'importe lequel des inputs suivants comme contexte pour un build :
- Le chemin relatif ou absolu vers un répertoire local
- Une URL distante d'un dépôt Git, tarball, ou fichier texte
- Un fichier texte ou tarball envoyé à la commande
docker build
via l'entrée standard
Contextes de système de fichiers
Lorsque votre contexte de build est un répertoire local, un dépôt Git distant, ou un fichier tar,
alors cela devient l'ensemble des fichiers auxquels le constructeur peut accéder pendant le
build. Les instructions de build telles que COPY
et ADD
peuvent référencer n'importe quel des
fichiers et répertoires dans le contexte.
Un contexte de build de système de fichiers est traité récursivement :
- Lorsque vous spécifiez un répertoire local ou un tarball, tous les sous-répertoires sont inclus
- Lorsque vous spécifiez un dépôt Git distant, le dépôt et tous les sous-modules sont inclus
Pour plus d'informations sur les différents types de contextes de système de fichiers que vous pouvez utiliser avec vos builds, voir :
Contextes de fichier texte
Lorsque votre contexte de build est un fichier texte, le constructeur interprète le fichier comme un Dockerfile. Avec cette approche, le build n'utilise pas de contexte de système de fichiers.
Pour plus d'informations, voir contexte de build vide.
Contexte local
Pour utiliser un contexte de build local, vous pouvez spécifier un chemin de fichier relatif ou absolu
à la commande docker build
. L'exemple suivant montre une commande build qui
utilise le répertoire courant (.
) comme contexte de build :
$ docker build .
...
#16 [internal] load build context
#16 sha256:23ca2f94460dcbaf5b3c3edbaaa933281a4e0ea3d92fe295193e4df44dc68f85
#16 transferring context: 13.16MB 2.2s done
...
Cela rend les fichiers et répertoires du répertoire de travail courant disponibles pour le constructeur. Le constructeur charge les fichiers dont il a besoin depuis le contexte de build quand nécessaire.
Vous pouvez également utiliser des tarballs locaux comme contexte de build, en envoyant les
contenus du tarball à la commande docker build
. Voir Tarballs.
Répertoires locaux
Considérez la structure de répertoire suivante :
.
├── index.ts
├── src/
├── Dockerfile
├── package.json
└── package-lock.json
Les instructions Dockerfile peuvent référencer et inclure ces fichiers dans le build si vous passez ce répertoire comme contexte.
# syntax=docker/dockerfile:1
FROM node:latest
WORKDIR /src
COPY package.json package-lock.json .
RUN npm ci
COPY index.ts src .
$ docker build .
Contexte local avec Dockerfile depuis stdin
Utilisez la syntaxe suivante pour construire une image en utilisant des fichiers sur votre système de fichiers local, tout en utilisant un Dockerfile depuis stdin.
$ docker build -f- <PATH>
La syntaxe utilise l'option -f (ou --file) pour spécifier le Dockerfile à utiliser, et elle utilise un trait d'union (-) comme nom de fichier pour instruire Docker de lire le Dockerfile depuis stdin.
L'exemple suivant utilise le répertoire courant (.) comme contexte de build, et construit une image en utilisant un Dockerfile passé via stdin en utilisant un here-document.
# créer un répertoire de travail
mkdir example
cd example
# créer un fichier d'exemple
touch somefile.txt
# construire une image en utilisant le répertoire courant comme contexte
# et un Dockerfile passé via stdin
docker build -t myimage:latest -f- . <<EOF
FROM busybox
COPY somefile.txt ./
RUN cat /somefile.txt
EOF
Tarballs locaux
Lorsque vous envoyez un tarball à la commande build, le build utilise le contenu du tarball comme contexte de système de fichiers.
Par exemple, étant donné le répertoire de projet suivant :
.
├── Dockerfile
├── Makefile
├── README.md
├── main.c
├── scripts
├── src
└── test.Dockerfile
Vous pouvez créer un tarball du répertoire et l'envoyer au build pour l'utiliser comme contexte :
$ tar czf foo.tar.gz *
$ docker build - < foo.tar.gz
Le build résout le Dockerfile depuis le contexte tarball. Vous pouvez utiliser le
flag --file
pour spécifier le nom et l'emplacement du Dockerfile relativement à
la racine du tarball. La commande suivante construit en utilisant test.Dockerfile
dans le tarball :
$ docker build --file test.Dockerfile - < foo.tar.gz
Contexte distant
Vous pouvez spécifier l'adresse d'un dépôt Git distant, tarball, ou fichier texte comme votre contexte de build.
- Pour les dépôts Git, le constructeur clone automatiquement le dépôt. Voir Dépôts Git.
- Pour les tarballs, le constructeur télécharge et extrait le contenu du tarball. Voir Tarballs.
Si le tarball distant est un fichier texte, le constructeur ne reçoit aucun contexte de système de fichiers, et suppose plutôt que le fichier distant est un Dockerfile. Voir Contexte de build vide.
Dépôts Git
Lorsque vous passez une URL pointant vers l'emplacement d'un dépôt Git comme argument
à docker build
, le constructeur utilise le dépôt comme contexte de build.
Le constructeur effectue un clone superficiel du dépôt, téléchargeant uniquement le commit HEAD, pas tout l'historique.
Le constructeur clone récursivement le dépôt et tous les sous-modules qu'il contient.
$ docker build https://github.com/user/myrepo.git
Par défaut, le constructeur clone le dernier commit sur la branche par défaut du dépôt que vous spécifiez.
Fragments d'URL
Vous pouvez ajouter des fragments d'URL à l'adresse du dépôt Git pour faire en sorte que le constructeur clone une branche, un tag, ou un sous-répertoire spécifique d'un dépôt.
Le format du fragment d'URL est #ref:dir
, où :
ref
est le nom de la branche, du tag, ou du hash de commitdir
est un sous-répertoire à l'intérieur du dépôt
Par exemple, la commande suivante utilise la branche container
,
et le sous-répertoire docker
dans cette branche, comme contexte de build :
$ docker build https://github.com/user/myrepo.git#container:docker
Le tableau suivant représente tous les suffixes valides avec leurs contextes de build :
Suffixe de syntaxe de build | Commit utilisé | Contexte de build utilisé |
---|---|---|
myrepo.git |
refs/heads/<branche par défaut> |
/ |
myrepo.git#mytag |
refs/tags/mytag |
/ |
myrepo.git#mybranch |
refs/heads/mybranch |
/ |
myrepo.git#pull/42/head |
refs/pull/42/head |
/ |
myrepo.git#:myfolder |
refs/heads/<branche par défaut> |
/myfolder |
myrepo.git#master:myfolder |
refs/heads/master |
/myfolder |
myrepo.git#mytag:myfolder |
refs/tags/mytag |
/myfolder |
myrepo.git#mybranch:myfolder |
refs/heads/mybranch |
/myfolder |
Lorsque vous utilisez un hash de commit comme ref
dans le fragment d'URL, utilisez la
chaîne SHA-1 complète de 40 caractères du commit. Un hash court, par exemple un hash
tronqué à 7 caractères, n'est pas supporté.
# ✅ Ceci fonctionne :
docker build github.com/docker/buildx#d4f088e689b41353d74f1a0bfcd6d7c0b213aed2
# ❌ Ceci ne fonctionne pas car le hash de commit est tronqué :
docker build github.com/docker/buildx#d4f088e
Garder le répertoire .git
Par défaut, BuildKit ne garde pas le répertoire .git
lors de l'utilisation de contextes Git.
Vous pouvez configurer BuildKit pour garder le répertoire en définissant l'
argument de build BUILDKIT_CONTEXT_KEEP_GIT_DIR
.
Ceci peut être utile si vous voulez récupérer des informations Git pendant votre build :
# syntax=docker/dockerfile:1
FROM alpine
WORKDIR /src
RUN --mount=target=. \
make REVISION=$(git rev-parse HEAD) build
$ docker build \
--build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
https://github.com/user/myrepo.git#main
Dépôts privés
Lorsque vous spécifiez un contexte Git qui est également un dépôt privé, le constructeur a besoin que vous fournissiez les identifiants d'authentification nécessaires. Vous pouvez utiliser soit l'authentification SSH soit basée sur token.
Buildx détecte et utilise automatiquement les identifiants SSH si le contexte Git que vous
spécifiez est une adresse SSH ou Git. Par défaut, ceci utilise $SSH_AUTH_SOCK
.
Vous pouvez configurer les identifiants SSH à utiliser avec le
flag --ssh
.
$ docker buildx build --ssh default [email protected]:user/private.git
Si vous voulez utiliser l'authentification basée sur token à la place, vous pouvez passer le token
en utilisant le
flag --secret
.
$ GIT_AUTH_TOKEN=<token> docker buildx build \
--secret id=GIT_AUTH_TOKEN \
https://github.com/user/private.git
NoteN'utilisez pas
--build-arg
pour les secrets.
Contexte distant avec Dockerfile depuis stdin
Utilisez la syntaxe suivante pour construire une image en utilisant des fichiers sur votre système de fichiers local, tout en utilisant un Dockerfile depuis stdin.
$ docker build -f- <URL>
La syntaxe utilise l'option -f (ou --file) pour spécifier le Dockerfile à utiliser, et elle utilise un trait d'union (-) comme nom de fichier pour instruire Docker de lire le Dockerfile depuis stdin.
Ceci peut être utile dans des situations où vous voulez construire une image depuis un dépôt qui ne contient pas de Dockerfile. Ou si vous voulez construire avec un Dockerfile personnalisé, sans maintenir votre propre fork du dépôt.
L'exemple suivant construit une image en utilisant un Dockerfile depuis stdin, et ajoute
le fichier hello.c
depuis le dépôt hello-world
sur GitHub.
docker build -t myimage:latest -f- https://github.com/docker-library/hello-world.git <<EOF
FROM busybox
COPY hello.c ./
EOF
Tarballs distants
Si vous passez l'URL vers un tarball distant, l'URL elle-même est envoyée au constructeur.
$ docker build http://server/context.tar.gz
#1 [internal] load remote build context
#1 DONE 0.2s
#2 copy /context /
#2 DONE 0.1s
...
L'opération de téléchargement sera effectuée sur l'hôte où le démon BuildKit
s'exécute. Notez que si vous utilisez un contexte Docker distant ou un
constructeur distant, ce n'est pas nécessairement la même machine que celle où vous exécutez la commande build.
BuildKit récupère le context.tar.gz
et l'utilise comme contexte de build.
Les contextes tarball doivent être des archives tar conformes au format tar
Unix standard et peuvent être compressés avec l'un des formats xz
, bzip2
, gzip
ou
identity
(pas de compression).
Contexte vide
Lorsque vous utilisez un fichier texte comme contexte de build, le constructeur interprète le fichier comme un Dockerfile. Utiliser un fichier texte comme contexte signifie que le build n'a pas de contexte de système de fichiers.
Vous pouvez construire avec un contexte de build vide lorsque votre Dockerfile ne dépend d'aucun fichier local.
Comment construire sans contexte
Vous pouvez passer le fichier texte en utilisant un flux d'entrée standard, ou en pointant vers l' URL d'un fichier texte distant.
$ docker build - < Dockerfile
Get-Content Dockerfile | docker build -
docker build -t myimage:latest - <<EOF
FROM busybox
RUN echo "hello world"
EOF
$ docker build https://raw.githubusercontent.com/dvdksn/clockbox/main/Dockerfile
Lorsque vous construisez sans contexte de système de fichiers, les instructions Dockerfile telles que
COPY
ne peuvent pas référencer des fichiers locaux :
$ ls
main.c
$ docker build -<<< $'FROM scratch\nCOPY main.c .'
[+] Building 0.0s (4/4) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 64B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2B 0.0s
=> ERROR [1/1] COPY main.c . 0.0s
------
> [1/1] COPY main.c .:
------
Dockerfile:2
--------------------
1 | FROM scratch
2 | >>> COPY main.c .
3 |
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 7ab2bb61-0c28-432e-abf5-a4c3440bc6b6::4lgfpdf54n5uqxnv9v6ymg7ih: "/main.c": not found
Fichiers .dockerignore
Vous pouvez utiliser un fichier .dockerignore
pour exclure des fichiers ou répertoires du
contexte de build.
# .dockerignore
node_modules
bar
Ceci aide à éviter d'envoyer des fichiers et répertoires non désirés au constructeur, améliorant la vitesse de build, surtout lors de l'utilisation d'un constructeur distant.
Nom de fichier et emplacement
Lorsque vous exécutez une commande build, le client build recherche un fichier nommé
.dockerignore
dans le répertoire racine du contexte. Si ce fichier existe, les
fichiers et répertoires qui correspondent aux motifs dans les fichiers sont supprimés du
contexte de build avant qu'il ne soit envoyé au constructeur.
Si vous utilisez plusieurs Dockerfiles, vous pouvez utiliser différents fichiers ignore pour chaque Dockerfile. Vous faites cela en utilisant une convention de nommage spéciale pour les fichiers ignore. Placez votre fichier ignore dans le même répertoire que le Dockerfile, et préfixez le fichier ignore avec le nom du Dockerfile, comme montré dans l'exemple suivant.
.
├── index.ts
├── src/
├── docker
│ ├── build.Dockerfile
│ ├── build.Dockerfile.dockerignore
│ ├── lint.Dockerfile
│ ├── lint.Dockerfile.dockerignore
│ ├── test.Dockerfile
│ └── test.Dockerfile.dockerignore
├── package.json
└── package-lock.json
Un fichier ignore spécifique au Dockerfile prend la précédence sur le fichier .dockerignore
à la racine du contexte de build si les deux existent.
Syntaxe
Le fichier .dockerignore
est une liste de motifs séparés par des nouvelles lignes similaire aux
globs de fichiers des shells Unix. Les barres obliques de début et de fin dans les motifs ignore sont
ignorées. Les motifs suivants excluent tous un fichier ou répertoire nommé bar
dans le sous-répertoire foo
sous la racine du contexte de build :
/foo/bar/
/foo/bar
foo/bar/
foo/bar
Si une ligne dans le fichier .dockerignore
commence par #
dans la colonne 1, alors cette ligne
est considérée comme un commentaire et est ignorée avant d'être interprétée par le CLI.
#/this/is/a/comment
Si vous êtes intéressé à apprendre les détails précis de la logique de correspondance de motifs .dockerignore
,
consultez le dépôt
moby/patternmatcher
sur GitHub, qui contient le code source.
Correspondance
L'extrait de code suivant montre un exemple de fichier .dockerignore
.
# comment
*/temp*
*/*/temp*
temp?
Ce fichier provoque le comportement de build suivant :
Règle | Comportement |
---|---|
# comment |
Ignoré. |
*/temp* |
Exclut les fichiers et répertoires dont les noms commencent par temp dans tout sous-répertoire immédiat de la racine. Par exemple, le fichier simple /somedir/temporary.txt est exclu, ainsi que le répertoire /somedir/temp . |
*/*/temp* |
Exclut les fichiers et répertoires commençant par temp de tout sous-répertoire qui est à deux niveaux sous la racine. Par exemple, /somedir/subdir/temporary.txt est exclu. |
temp? |
Exclut les fichiers et répertoires dans le répertoire racine dont les noms sont une extension d'un caractère de temp . Par exemple, /tempa et /tempb sont exclus. |
La correspondance est effectuée en utilisant les règles de la fonction
filepath.Match
de Go.
Une étape de prétraitement utilise la fonction
filepath.Clean
de Go
pour supprimer les espaces et enlever .
et ..
.
Les lignes qui sont vides après le prétraitement sont ignorées.
NotePour des raisons historiques, le motif
.
est ignoré.
Au-delà des règles filepath.Match
de Go, Docker prend également en charge une chaîne joker spéciale
**
qui correspond à un nombre quelconque de répertoires (y compris zéro). Par
exemple, **/*.go
exclut tous les fichiers qui se terminent par .go
trouvés n'importe où dans le
contexte de build.
Vous pouvez utiliser le fichier .dockerignore
pour exclure le Dockerfile
et
les fichiers .dockerignore
. Ces fichiers sont toujours envoyés au constructeur car ils sont
nécessaires pour exécuter le build. Mais vous ne pouvez pas copier les fichiers dans l'image en utilisant
ADD
, COPY
, ou des montages bind.
Négation des correspondances
Vous pouvez préfixer les lignes avec un !
(point d'exclamation) pour faire des exceptions aux
exclusions. Voici un exemple de fichier .dockerignore
qui utilise ce
mécanisme :
*.md
!README.md
Tous les fichiers markdown directement sous le répertoire de contexte sauf README.md
sont
exclus du contexte. Notez que les fichiers markdown sous les sous-répertoires sont
toujours inclus.
Le placement des règles d'exception !
influence le comportement : la dernière ligne du
.dockerignore
qui correspond à un fichier particulier détermine s'il est
inclus ou exclu. Considérez l'exemple suivant :
*.md
!README*.md
README-secret.md
Aucun fichier markdown n'est inclus dans le contexte sauf les fichiers README autres que
README-secret.md
.
Maintenant considérez cet exemple :
*.md
README-secret.md
!README*.md
Tous les fichiers README sont inclus. La ligne du milieu n'a aucun effet car
!README*.md
correspond à README-secret.md
et vient en dernier.
Contextes nommés
En plus du contexte de build par défaut (l'argument positionnel de la
commande docker build
), vous pouvez également passer des contextes nommés supplémentaires aux builds.
Les contextes nommés sont spécifiés en utilisant le flag --build-context
, suivi d'une
paire nom-valeur. Ceci vous permet d'inclure des fichiers et répertoires de sources multiples
pendant le build, tout en les gardant logiquement séparés.
$ docker build --build-context docs=./docs .
Dans cet exemple :
- Le contexte nommé
docs
pointe vers le répertoire./docs
. - Le contexte par défaut (
.
) pointe vers le répertoire de travail courant.
Utilisation des contextes nommés dans un Dockerfile
Les instructions Dockerfile peuvent référencer les contextes nommés comme s'ils étaient des étapes dans un build multi-étapes.
Par exemple, le Dockerfile suivant :
- Utilise une instruction
COPY
pour copier des fichiers depuis le contexte par défaut dans l' étape de build courante. - Monte les fichiers dans un contexte nommé pour traiter les fichiers dans le cadre du build.
# syntax=docker/dockerfile:1
FROM buildbase
WORKDIR /app
# Copier tous les fichiers depuis le contexte par défaut dans /app/src dans le conteneur de build
COPY . /app/src
RUN make bin
# Monter les fichiers depuis le contexte nommé "docs" pour construire la documentation
RUN --mount=from=docs,target=/app/docs \
make manpages
Cas d'usage pour les contextes nommés
Utiliser des contextes nommés permet une plus grande flexibilité et efficacité lors de la construction d'images Docker. Voici quelques scénarios où utiliser des contextes nommés peut être utile :
Exemple : combiner des sources locales et distantes
Vous pouvez définir des contextes nommés séparés pour différents types de sources. Par exemple, considérez un projet où le code source de l'application est local, mais les scripts de déploiement sont stockés dans un dépôt Git :
$ docker build --build-context scripts=https://github.com/user/deployment-scripts.git .
Dans le Dockerfile, vous pouvez utiliser ces contextes indépendamment :
# syntax=docker/dockerfile:1
FROM alpine:latest
# Copier le code de l'application depuis le contexte principal
COPY . /opt/app
# Exécuter les scripts de déploiement en utilisant le contexte "scripts" distant
RUN --mount=from=scripts,target=/scripts /scripts/main.sh
Exemple : builds dynamiques avec des dépendances personnalisées
Dans certains scénarios, vous pourriez avoir besoin d'injecter dynamiquement des fichiers de configuration ou des dépendances dans le build depuis des sources externes. Les contextes nommés rendent ceci simple en vous permettant de monter différentes configurations sans modifier le contexte de build par défaut.
$ docker build --build-context config=./configs/prod .
Exemple de Dockerfile :
# syntax=docker/dockerfile:1
FROM nginx:alpine
# Utiliser le contexte "config" pour les configurations spécifiques à l'environnement
COPY --from=config nginx.conf /etc/nginx/nginx.conf
Exemple : épingler ou remplacer des images
Vous pouvez référencer des contextes nommés dans un Dockerfile de la même façon que vous pouvez référencer une image. Cela signifie que vous pouvez changer une référence d'image dans votre Dockerfile en la remplaçant par un contexte nommé. Par exemple, étant donné le Dockerfile suivant :
FROM alpine:3.21
Si vous voulez forcer la référence d'image à résoudre vers une version différente, sans changer le Dockerfile, vous pouvez passer un contexte avec le même nom au build. Par exemple :
docker buildx build --build-context alpine:3.21=docker-image://alpine:edge .
Le préfixe docker-image://
marque le contexte comme une référence d'image. La
référence peut être une image locale ou une image dans votre registre.
Contextes nommés avec Bake
Bake est un outil intégré dans docker build
qui
vous permet de gérer votre configuration de build avec un fichier de configuration. Bake prend
entièrement en charge les contextes nommés.
Pour définir des contextes nommés dans un fichier Bake :
target "app" {
contexts = {
docs = "./docs"
}
}
Ceci est équivalent à l'invocation CLI suivante :
$ docker build --build-context docs=./docs .
Lier des cibles avec des contextes nommés
En plus de rendre les builds complexes plus gérables, Bake fournit également
des fonctionnalités supplémentaires en plus de ce que vous pouvez faire avec docker build
en CLI.
Vous pouvez utiliser des contextes nommés pour créer des pipelines de build, où une cible dépend
de et construit par-dessus une autre. Par exemple, considérez une configuration Docker build
où vous avez deux Dockerfiles :
base.Dockerfile
: pour construire une image de baseapp.Dockerfile
: pour construire une image d'application
Le app.Dockerfile
utilise l'image produite par base.Dockerfile
comme son image de base :
FROM mybaseimage
Normalement, vous devriez construire l'image de base en premier, puis soit la charger
dans le magasin d'images local de Docker Engine ou la pousser vers un registre. Avec Bake, vous
pouvez référencer d'autres cibles directement, créant une dépendance entre la cible app
et la cible base
.
target "base" {
dockerfile = "base.Dockerfile"
}
target "app" {
dockerfile = "app.Dockerfile"
contexts = {
# le préfixe target: indique que 'base' est une cible Bake
mybaseimage = "target:base"
}
}
Avec cette configuration, les références à mybaseimage
dans app.Dockerfile
utilisent
les résultats de la construction de la cible base
. Construire la cible app
déclenchera
également une reconstruction de mybaseimage
, si nécessaire :
$ docker buildx bake app
Lecture complémentaire
Pour plus d'informations sur le travail avec les contextes nommés, voir :