TL;DR
Si vous utilisez ARG avec un Dockerfile de construction en plusieurs étapes, sachez que la portée est fermée à l'intérieur de la scène! Déclarez l'ARG à utiliser pour chaque étape! De plus, si l'ARG utilisé en plusieurs étapes a une valeur par défaut, définissez un ARG global et mettez-y la valeur par défaut!
Ce n'est pas grave si vous faites comme ça!
Dockerfile
#S'il existe une valeur par défaut pour l'ARG qui est couramment utilisée à chaque étape, définissez-la avant le premier FROM.
ARG YOUR_ARG="Default value"
FROM alpine:latest as first_stage
#ARG doit être déclaré pour chaque étape utilisée.
ARG YOUR_ARG
RUN echo "1st stage: ${YOUR_ARG}"
FROM alpine:latest as second_stage
#ARG doit être déclaré pour chaque étape utilisée.
ARG YOUR_ARG
RUN echo "2nd stage: ${YOUR_ARG}"
Dans les versions en plusieurs étapes, la portée d'ARG et d'ENV semble être limitée par étape. Le saviez-vous tous? Je ne savais pas jusqu'à ce que je réalise que je ne pouvais pas faire référence à la valeur d'ARG dans l'étape du Dockerfile que j'ai créé.
D'après ce commentaire
Correct, Dockerfile instructions, including ENV vars and ARG are scoped per build-stage, and will not be preserved in the next stage; this is by design. You can, however, set a global ARG (set before the first build-stage), and use that value in each build-stage; Les instructions Dockerfile, y compris ENV et ARG, sont définies pour chaque étape de construction et ne seront pas reportées à l'étape suivante. C'est ce que c'est par conception. Cependant, si vous utilisez l'ARG global (défini avant la première étape de construction), vous pouvez tirer parti de cette valeur pour chaque étape de construction.
... Apparemment ... Vraiment?
Il a également été fermement répertorié dans le Document officiel.
La portée variable de l'instruction ARG est jusqu'à la fin de l'étape de construction au cours de laquelle elle est définie. Si vous souhaitez utiliser ARG dans plusieurs étapes de construction, vous devez spécifier l'instruction ARG individuellement.
Quand j'ai lu le document pour la première fois, j'ai eu l'impression de penser: «Ahhhhh, je l'ai complètement compris», sans connaître le sens de l'étape de construction. .. ..
Voyons en fait comment ARG fonctionne dans une construction en plusieurs étapes.
Au moment de la rédaction de cet article, nous avons confirmé l'opération avec les versions suivantes.
# docker --version
Docker version 18.09.1, build 4c52b90
Dockerfile
Le Dockerfile utilisé dans cette vérification est le suivant.
Dockerfile
#ARG1 déclare globalement et définit les valeurs par défaut globales.
ARG ARG1="arg1 global default value"
#ARG2 déclare globalement mais ne définit pas de valeur par défaut globale.
ARG ARG2
#ARG3 ne déclare pas globalement.
# ARG ARG3
FROM alpine:latest as first_stage
# first_Dans l'étape, chaque ARG est déclaré et la valeur par défaut de la portée est définie.
ARG ARG1="arg1 first stage value"
ARG ARG2="arg2 first stage value"
ARG ARG3="arg3 first stage value"
RUN echo -e "first_stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
FROM alpine:latest as second_stage
# second_Dans l'étape, chaque ARG est déclaré, mais aucune valeur par défaut dans la portée n'est définie.
ARG ARG1
ARG ARG2
ARG ARG3
RUN echo -e "second_stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
FROM alpine:latest as third_stage
# third_Au stade, ne déclarez pas tous les ARG.
# ARG ARG1
# ARG ARG2
# ARG ARG3
RUN echo -e "third_stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
Chaque ARG est défini comme suit.
Nom ARG | Réglages |
---|---|
ARG1 | Défini comme un ARG global. Spécifiez également la valeur par défaut. |
ARG2 | Défini comme un ARG global. Aucune valeur par défaut n'est spécifiée. |
ARG3 | Ne définissez pas comme ARG global. |
De plus, chaque étape est définie comme suit.
Nom de scène | Réglages |
---|---|
first_stage | Déclarez chaque ARG. Définissez la valeur par défaut dans la scène. |
second_stage | Déclarez chaque ARG. Ne définissez pas la valeur par défaut dans la scène. |
third_stage | Ne déclarez pas ARG. |
--build-arg
Construire sans spécificationLors de la construction de Docker Image, essayez de construire sans spécifier la valeur avec --build-arg
.
# docker build . --no-cache
Sending build context to Docker daemon 14.85kB
...snip...
Step 7/14 : RUN echo -e "1st stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in 2bbe78634ee8
first_stage:
ARG1=arg1 first stage value
ARG2=arg2 first stage value
ARG3=arg3 first stage value
...snip...
Step 12/14 : RUN echo -e "2nd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in 0c28af93ea9b
second_stage:
ARG1=arg1 global default value
ARG2=
ARG3=
...snip...
Step 14/14 : RUN echo -e "3rd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in cbca9ed88691
third_stage:
ARG1=
ARG2=
ARG3=
...snip...
--build-arg
Construire avec des spécificationsMaintenant, essayez de construire avec la valeur spécifiée par --build-arg
.
# docker build --build-arg ARG1="build arg1 value" --build-arg ARG2="build arg2 value" --build-arg ARG3="build arg3 value" . --no-cache
Sending build context to Docker daemon 14.85kB
...snip...
Step 7/14 : RUN echo -e "1st stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in 10b37c5a524b
first_stage:
ARG1=build arg1 value
ARG2=build arg2 value
ARG3=build arg3 value
...snip...
Step 12/14 : RUN echo -e "2nd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in e70e3ff9fe9b
second_stage:
ARG1=build arg1 value
ARG2=build arg2 value
ARG3=build arg3 value
...snip...
Step 14/14 : RUN echo -e "3rd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in e675e8f648e8
third_stage:
ARG1=
ARG2=
ARG3=
...snip...
--build-arg
. Ceci est conforme à ce qui est décrit dans Official Document ARG Defaults. La valeur spécifiée par --build-arg
est prioritaire à la fois sur la valeur par défaut globale et la valeur par défaut en cours.--build-arg
, elle semble toujours indisponible à moins qu'elle ne soit déclarée à ce stade.--build-arg
[Haute priorité]C'est ça.
C'est une promotion du projet qui m'a poussé à remarquer le comportement d'ARG en construction en plusieurs étapes.
Exploitons facilement le serveur Bedrock de Minecraft! C'est un projet à l'effet. Minecraft se met parfois à jour, mais le client est principalement mis à jour seul, mais Bedrock Server n'est pas mis à jour automatiquement, téléchargeant manuellement la nouvelle version et extrayant le fichier Zip pour extraire le fichier binaire. J'ai dû le remplacer et redémarrer le service ... ou quelque chose comme ça. Ce projet ne doit être configuré qu'une seule fois et le serveur Bedrock sera mis à jour automatiquement! Au fait, Docker est utilisé pour construire Bedrock Server, donc il ne pollue pas l'environnement!
Merci!
Vraiment fait.