Ne comprenant pas ce qui se passe lorsque j'essaie d'exécuter deux commandes au moment de l'exécution via la directive CMD dans `Dockerfile. J'ai supposé que cela devrait fonctionner:
CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]
Mais ça ne marche pas. Le conteneur n'a pas commencé. Donc je devais le faire comme ça:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
Je ne comprends pas. Pourquoi donc? Pourquoi la première ligne n'est pas la bonne façon? Quelqu'un peut-il m'expliquer ces trucs "format shell CMD vs format JSON, etc."? En mots simples.
Juste pour noter - le même était avec command:
directive dans docker-compose.yml
, comme prévu.
exec
formulaire, car c'est le formulaire préféré? Pourquoi c'est préféré? Ou devrais-je utiliser unshell
formulaire plus simple ?CMD [ "sh", "-c", "echo", "$HOME"]
. Pourquoi pasCMD ["sh", "-c", "echo $HOME"]
ou d'ailleursCMD ["sh -c echo $HOME"]
?Ne rend pas les choses difficiles pour toi. Il suffit de créer un fichier bash "start.sh":
dans votre Dockerfile faire:
la source
La syntaxe json de
CMD
(etRUN
etENTRYPOINT
) transmet les arguments au noyau directement en tant qu'exec syscall. Il n'y a pas de séparation de la commande des arguments par des espaces, d'échappements de guillemets, de redirection IO, de substitution de variable, de canalisation entre les commandes, d'exécution de plusieurs commandes, etc., dans le syscall de exec. L'appel système ne prend que l'exécutable à exécuter et la liste des arguments à transmettre à cet exécutable, et il l'exécute.Les caractères tels que
$
développer les variables,;
séparer les commandes,(espace) séparer les arguments
&&
et||
chaîner les commandes,>
rediriger la sortie,|
diriger entre les commandes, etc., sont autant de fonctionnalités du shell et nécessitent quelque chose comme/bin/sh
ou/bin/bash
pour les interpréter et les implémenter.Si vous passez à la syntaxe de chaîne de
CMD
, docker exécutera votre commande avec un shell:Sinon, votre deuxième syntaxe fait exactement la même chose:
Notez que je ne recommande pas d'exécuter plusieurs commandes de cette manière à l'intérieur d'un conteneur, car il n'y a pas de traitement d'erreur si votre première commande échoue, surtout si elle s'exécute en arrière-plan. Vous laissez également un shell s'exécutant en tant que pid 1 à l'intérieur du conteneur, ce qui interrompra la gestion des signaux, ce qui entraînera un délai de 10 secondes et une destruction inutile de votre conteneur par le menu fixe. Le traitement du signal peut être atténué en utilisant la
exec
commande shell :Cependant, la gestion silencieuse des processus en arrière-plan nécessite que vous passiez à une sorte de gestionnaire multi-processus tel que supervisord ou, de préférence, divisez votre application en plusieurs conteneurs et les déployez avec un logiciel comme docker-compose.
la source
Je suppose que la première commande échoue car sous la forme DOCKER CMD, seul le premier paramètre est exécuté, le reste est introduit dans cette commande.
La seconde forme fonctionne car toutes les commandes séparées de ";" sont introduits dans la commande sh, qui les exécute.
la source
Je ne pense pas que vous devriez mettre une virgule après "commencer"
à la place d'utiliser
essayer
comme docker utilise "sh -c", la commande ci-dessus sera exécutée comme ci-dessous
la source
sh -c
dans ce scénario.