Je suis nouveau chez Docker et j'ai du mal à installer le conteneur Docker comme je le souhaite. J'ai une application nodejs qui peut prendre deux paramètres lors du démarrage. Par exemple, je peux utiliser
node server.js 0 dev
ou
node server.js 1 prod
pour basculer entre le mode de production et le mode dev et déterminer si le cluster doit être activé. Maintenant, je veux créer une image de menu fixe avec des arguments pour faire la même chose, la seule chose que je puisse faire jusqu’à présent est d’ajuster le fichier Dockerfile pour avoir une ligne.
CMD [ "node", "server.js", "0", "dev"]
et
docker build -t me/app .
pour construire le docker.
Ensuite docker run -p 9000:9000 -d me/app
pour exécuter le menu fixe.
Mais si je veux passer en mode prod, je dois changer le CMD Dockerfile pour qu’il soit
CMD [ "node", "server.js", "1", "prod"]
,
et j'ai besoin de tuer l'ancien qui écoute sur le port 9000 et de reconstruire l'image. J'aimerais avoir quelque chose comme
docker run -p 9000:9000 environment=dev cluster=0 -d me/app
pour créer une image et exécuter la commande nodejs avec les arguments "environment" et "cluster", il est donc inutile de modifier le fichier Docker et de reconstruire le menu fixe. Comment puis-je accomplir cela?
Assurez-vous que votre fichier Docker déclare une variable d’environnement avec ENV
:
ENV environment default_env_value
ENV cluster default_cluster_value
Le ENV <key> <value>
forme peut être remplacé en ligne .
Ensuite, vous pouvez passer une variable d’environnement avec docker run
docker run -p 9000:9000 -e environment=dev -e cluster=0 -d me/app
Ou vous pouvez définissez-les dans votre fichier de composition :
node:
environment:
- environment=dev
- cluster=0
Votre fichier Dockerfile CMD
peut utiliser cette variable d'environnement, mais, comme indiqué dans le numéro 5509 , vous devez le faire dans un fichier sh -c
forme:
CMD ["sh", "-c", "node server.js ${cluster} ${environment}"]
L’explication est que le shell est responsable du développement des variables d’environnement et non de Docker. Lorsque vous utilisez la syntaxe JSON , vous demandez explicitement que votre commande ignore le shell et soit exécutée directement.
Même idée avec Builder RUN (s'applique également à CMD
):
Contrairement au formulaire Shell, le formulaire exec n'invoque pas de commande Shell.
Cela signifie que le traitement Shell normal ne se produit pas.Par exemple,
RUN [ "echo", "$HOME" ]
ne fera pas de substitution de variable sur$HOME
. Si vous souhaitez un traitement Shell, utilisez le formulaire Shell ou exécutez-le directement, par exemple:RUN [ "sh", "-c", "echo $HOME" ]
.Lors de l'utilisation du formulaire exec et de l'exécution directe d'un shell, comme c'est le cas pour le formulaire shell, c'est le shell qui développe les variables d'environnement, pas le menu fixe.
Une autre option consiste à utiliser ENTRYPOINT
pour spécifier que node
est l'exécutable à exécuter et CMD
pour fournir les arguments. . Les documents ont un exemple dans exemple EXEC de la forme ENTRYPOINT .
En utilisant cette approche, votre Dockerfile ressemblera à quelque chose comme:
FROM ...
ENTRYPOINT [ "node", "server.js" ]
CMD [ "0", "dev" ]
L'exécuter dans dev utiliserait la même commande
docker run -p 9000:9000 -d me/app
et l'exécuter dans prod vous passeriez les paramètres à la commande d'exécution
docker run -p 9000:9000 -d me/app 1 prod
Vous voudrez peut-être omettre entièrement CMD
et toujours y passer 0 dev
ou 1 prod
comme arguments de la commande run. Ainsi, vous ne démarrez pas accidentellement un conteneur prod dans dev ou un conteneur dev dans prod.
Pour ce faire, les conteneurs Docker utilisent généralement des variables d’environnement:
docker run -p 9000:9000 -e NODE_ENV=dev -e CLUSTER=0 -d me/app