Le conteneur Docker s'arrêtera automatiquement après «docker run -d»

333

Selon le tutoriel que j'ai lu jusqu'à présent, l'utilisation de " docker run -d" démarrera un conteneur à partir de l'image et le conteneur s'exécutera en arrière-plan. Voici à quoi cela ressemble, nous pouvons voir que nous avons déjà un identifiant de conteneur.

root@docker:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d

Mais si j'ai couru " docker ps", rien n'a été retourné.

J'ai donc essayé " docker ps -a", je peux voir le conteneur déjà sorti:

root@docker:/home/root# docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                         PORTS               NAMES
605e3928cddd        centos:latest         "/bin/bash"         31 minutes ago      Exited (0) 31 minutes ago                          kickass_swartz

Quelque chose que j'ai fait de mal? Comment puis-je résoudre ce problème?

J John
la source
1
"docker run hello-world" <== fonctionne parfaitement, mais si je lance "docker run -d hello-world", je ne parviens toujours pas à obtenir un conteneur en cours d'exécution.
J John
5
J'ai eu un problème similaire, mais je l'ai fait fonctionner en utilisant docker run -it -d <image> /bin/bashceci démarre un shell bash de manière interactive et ne ferme pas le conteneur car le processus shell est actif.
Rtsne42

Réponses:

495

Le fichier docker centos a une commande par défaut bash.

Cela signifie que lorsqu'il est exécuté en arrière-plan ( -d), le shell se ferme immédiatement.

Mise à jour 2017

Les versions plus récentes de docker autorisent l'exécution d'un conteneur à la fois en mode détaché et en mode de premier plan ( -t, -iou -it)

Dans ce cas, vous n'avez besoin d'aucune commande supplémentaire et cela suffit:

docker run -t -d centos

Le bash attendra en arrière-plan.
Cela a été rapporté dans un premier temps Kalyani-Chaudhari « s réponse et détaillée en haricot jersey » s de réponse .

vonc@voncvb:~$ d ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4a50fd9e9189        centos              "/bin/bash"         8 seconds ago       Up 2 seconds                            wonderful_wright

Notez que pour l' alpin , Marinos An rapporte dans les commentaires :

docker run -t -d alpine/gitne maintient pas le processus.
Devais faire:docker run --entrypoint "/bin/sh" -it alpine/git


Réponse originale (2015)

Comme mentionné dans cet article :

Au lieu de fonctionner avec docker run -i -t image your-command, l'utilisation -dest recommandée car vous pouvez exécuter votre conteneur avec une seule commande et vous n'avez pas besoin de détacher le terminal du conteneur en appuyant sur Ctrl+ P+ Q.

Cependant, il y a un problème avec l' -doption. Votre conteneur s'arrête immédiatement, sauf si les commandes ne s'exécutent pas au premier plan .
Docker nécessite votre commande pour continuer à fonctionner au premier plan. Sinon, il pense que vos applications s'arrêtent et arrêtent le conteneur.

Le problème est que certaines applications ne s'exécutent pas au premier plan. Comment pouvons-nous faciliter les choses?

Dans cette situation, vous pouvez ajouter tail -f /dev/nullà votre commande.
Ce faisant, même si votre commande principale s'exécute en arrière-plan, votre conteneur ne s'arrête pas car la queue continue de s'exécuter au premier plan.

Cela fonctionnerait donc:

docker run -d centos tail -f /dev/null

Un docker psmontrerait le conteneur Centos toujours en cours d'exécution.

De là, vous pouvez vous y attacher ou vous en détacher (ou docker execcertaines commandes).

VonC
la source
Désolé, encore une question, j'ai un script à exécuter au démarrage, il semble que /etc/rc.d/rc.local ne fonctionne plus (mon état d'esprit traite toujours Docker comme OS), je suppose que le fichier Docker est une meilleure option dans ce Cas?
J John
5
@GuruprasadGV C'est prévu. Au lieu d'utiliser Docker Attach, utilisez docker exec -it <yourContainer> bash.
VonC
3
Cela fonctionne également si vous ajoutez la commande tail à la fin d'un fichier de point d'entrée.
yara
2
J'ai utilisé sshd comme ma dernière commande (longue). Vous pouvez ensuite utiliser ssh sur votre conteneur comme vous le feriez sur une machine virtuelle (une fois que vous avez défini .ssh / authorized_keys, etc.) ... Vous pouvez également continuer à configurer le conteneur en utilisant ansible.
andrew pate
1
J'ai fini par faire cela pour exécuter ma commande plus l'ancien correctif répertorié ci-dessus: docker run image_name / bin / bash -c "my / command && tail -f / dev / null"
Geordie
58

Selon cette réponse , l'ajout de l' -tindicateur empêchera la sortie du conteneur lors de l'exécution en arrière-plan. Vous pouvez ensuite utiliser docker exec -i -t <image> /bin/bashpour entrer dans une invite de shell.

docker run -t -d <image> <command>

Il semble que l'option -t ne soit pas très bien documentée , bien que l'aide indique qu'elle "alloue un pseudo-ATS".

cjsimon
la source
10
Agréable. Semble moins hacky que l'ajouttail -f /dev/null
Scarysize
Merci! Sur la mince chance que cela aide quelqu'un, cela ne se comporte pas bien dans Emacs Eshell.
Peter Becich
2
docker run -t -d --name mysql -p 3306:3306 mysql- ne fonctionne pas pour moi (ubuntu 14.04.5): STATUS = Quitté (1) il y a 4 secondes
Putnik
J'ai trouvé que vous n'avez pas besoin de <commande> ici, sauf si vous le souhaitez. Étrangement, cela fonctionne aussi pour remplacer -t par -i (interactif). Le document mentionne que l'utilisation combinée de -t et -i se comportera comme un shell.
jersey bean
44

Contexte

Un conteneur Docker exécute un processus (la "commande" ou "point d'entrée") qui le maintient en vie. Le conteneur continuera à s'exécuter tant que la commande continuera à s'exécuter.

Dans votre cas, la commande ( /bin/bash, par défaut, on centos:latest) se ferme immédiatement (comme le fait bash lorsqu'il n'est pas connecté à un terminal et n'a rien à exécuter).

Normalement, lorsque vous exécutez un conteneur en mode démon (avec -d), le conteneur exécute une sorte de processus démon (comme httpd). Dans ce cas, tant que le démon httpd est en cours d'exécution, le conteneur restera actif.

Ce que vous semblez essayer de faire, c'est de maintenir le conteneur en vie sans qu'un processus démon ne s'exécute à l'intérieur du conteneur. C'est quelque peu étrange (car le conteneur ne fait rien d'utile tant que vous n'interagissez pas avec lui, peut-être avec docker exec), mais il y a certains cas où il peut être judicieux de faire quelque chose comme ça.

(Vouliez-vous dire d'accéder à une invite bash à l'intérieur du conteneur? C'est facile! docker run -it centos:latest)

Solution

Un moyen simple de conserver indéfiniment un conteneur en mode démon consiste à exécuter sleep infinityla commande du conteneur. Cela ne repose pas sur des choses étranges comme l'allocation d'un ATS en mode démon. Bien qu'il repose sur des choses étranges comme l'utilisation sleepcomme commande principale.

$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID  IMAGE         COMMAND          CREATED       STATUS       PORTS NAMES
d651c7a9e0ad  centos:latest "sleep infinity" 2 seconds ago Up 2 seconds       nervous_visvesvaraya

Solution alternative

Comme indiqué par cjsimon, l' -toption alloue un "pseudo-tty". Cette astuce consiste à continuer à fonctionner indéfiniment car il pense qu'il est connecté à un TTY interactif (même si vous n'avez aucun moyen d'interagir avec ce TTY particulier si vous ne passez pas -i). Quoi qu'il en soit, cela devrait aussi faire l'affaire:

$ docker run -t -d centos:latest

Pas sûr à 100% si -tcela produira d'autres interactions étranges; laissez peut-être un commentaire ci-dessous si c'est le cas.

mkasberg
la source
Notez que cela ne fonctionne pas en alpin car le sommeil de BusyBox n'accepte pas infinity.
John Kugelman
cela m'a aidé à dépanner une image amazon-linux, merci
influent
18

Salut ce problème est dû au fait que les conteneurs Docker se terminent s'il n'y a aucune application en cours d'exécution dans le conteneur.

-d 

L'option consiste simplement à exécuter un conteneur en mode démon.

Donc, l'astuce pour faire fonctionner votre conteneur en continu est de pointer vers un fichier shell dans docker qui gardera votre application en cours d'exécution. Vous pouvez essayer avec un fichier start.sh

Eg: docker run -d centos sh /yourlocation/start.sh

Ce start.sh devrait pointer vers une application sans fin.

Dans le cas où vous ne voulez pas qu'une application soit en cours d'exécution, vous pouvez installer monitce qui gardera votre conteneur Docker en cours d'exécution. Veuillez nous faire savoir si ces deux cas ont fonctionné pour que vous continuiez à faire fonctionner votre conteneur.

Bonne chance

Pratik
la source
12

Vous pouvez accomplir ce que vous voulez avec:

docker run -t -d <image-name>

ou

docker run -i -d <image-name>

ou

docker run -it -d <image-name>

Le paramètre de commande tel que suggéré par d'autres réponses (c'est-à-dire tail -f / dev / null) est complètement facultatif et n'est PAS requis pour que votre conteneur continue de fonctionner en arrière-plan.

Notez également que la documentation Docker suggère que la combinaison des options -i et -t entraînera son comportement comme un shell.

Voir:

https://docs.docker.com/engine/reference/run/#foreground

jersey bean
la source
9

J'ai cet extrait de code exécuté à partir du ENTRYPOINTdans mon fichier docker:

while true
do
    echo "Press [CTRL+C] to stop.."
    sleep 1
done

Exécutez l'image de docker intégrée en tant que:

docker run -td <image name>

Connectez-vous au shell du conteneur:

docker exec -it <container id> /bin/bash
Binita Bharati
la source
Est-ce la solution pour laquelle vous avez créé une boucle infinie? : D
Muhammad SaLman
8

exécuter la commande comme suit:

docker run -t -d <image-name>

si vous souhaitez spécifier le port, commandez comme ci-dessous:

docker run -t -d -p <port-no> <image-name>

vérifiez le conteneur en cours d'exécution à l'aide de la commande suivante:

docker ps
kalyani chaudhari
la source
En fait, j'aime le mieux cette réponse, car la réponse la plus populaire suggère que vous avez besoin d'une commande (c'est-à-dire tail -f / dev / null). La commande est complètement facultative. La clé ici est d'utiliser -t. J'ai également trouvé que -i fonctionne à la place de -t, ou vous pouvez également utiliser les deux -it combinés (comme la documentation le suggère, il fonctionnera comme un shell).
jersey bean
Y a-t-il un avantage à utiliser -t -dvs -i -d? Les deux garderont le conteneur en marche.
wisbucky
5

Docker nécessite votre commande pour continuer à fonctionner au premier plan. Sinon, il pense que vos applications s'arrêtent et arrêtent le conteneur.

Donc, si votre script d'entrée de docker est un processus d'arrière-plan comme suit:

/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &

Le «&» fait s'arrêter et quitter le conteneur si aucun autre processus de premier plan n'est déclenché plus tard. Donc, la solution consiste simplement à supprimer le «&» ou à avoir un autre CMD de premier plan qui s'exécute après , tel

tail -f server.log
Peiming Hu
la source
Pourrait vouloir touchce fichier en premier, au cas où vous ne pourriez pas trouver un fichier journal.
Samuel Elh
Habituellement, le fichier journal I tail est le journal actuel du serveur ou la sortie de redirection, qui devrait déjà être là après le démarrage du processus.
Peiming Hu
4

Le conteneur Docker se ferme si la tâche à l'intérieur est terminée, donc si vous voulez la garder en vie même si elle n'a pas de travail ou est déjà terminée, vous pouvez le faire docker run -di image. Après cela, docker container lsvous le verrez fonctionner.

Vrangz
la source
3

Peut-être que ce n'est que moi, mais sur CentOS 7.3.1611 et Docker 1.12.6, mais j'ai finalement dû utiliser une combinaison des réponses publiées par @VonC et @Christopher Simon pour que cela fonctionne de manière fiable. Rien de ce que j'ai fait avant cela n'empêcherait le conteneur de se quitter après avoir exécuté CMD avec succès. Je démarre oracle-xe-11Gr2 et sshd.

Dockerfile

...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null

Ensuite, ajoutez -d -t et -i pour exécuter

docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611 

Enfin après des heures à me frapper la tête contre le mur

ssh -v [email protected] -p 5022
...
[email protected]'s password: 
debug1: Authentication succeeded (password).

Pour une raison quelconque, ce qui précède se terminera après l'exécution de CMD si la queue -f est supprimée, ou si l'une des options -t -d -i est omise.

steven87vt
la source
1

J'ai eu le même problème, juste ouvrir un autre terminal avec un bash dessus a fonctionné pour moi:

créer un conteneur:

docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557

conteneur de démarrage:

docker start 52bbc9b30557

lancez bash pour maintenir le conteneur en marche:

docker exec -it 52bbc9b30557 bash

processus de démarrage dont vous avez besoin:

docker exec -it 52bbc9b30557 /path_to_cool_your_app
Steef
la source
1

Si vous utilisez CMD à la fin de votre Dockerfile, vous pouvez ajouter le code à la fin. Cela ne fonctionnera que si votre docker est construit sur Ubuntu ou sur tout système d'exploitation pouvant utiliser Bash.

&& /bin/bash

En bref, la fin de votre Dockerfile ressemblera à quelque chose comme ça.

...

CMD ls && ... && /bin/bash

Donc, si vous avez quelque chose qui s'exécute automatiquement après avoir exécuté votre image de docker, et lorsque la tâche est terminée, le terminal bash sera actif dans votre docker. Ainsi, vous pouvez entrer vos commandes shell.

Ekin
la source
1

L'exécution de Docker avec le mode interactif peut résoudre le problème.

Voici l'exemple pour exécuter l'image avec et sans mode interactif

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker run -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c95354966a18

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

NOMS DE PORTS D'ÉTAT CRÉÉS PAR COMMANDE D'IMAGE ID DE CONTENANT

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker run -d -t -i test_again1.0 bash c3d6a9529fd70c5b2dc2d7e90fe662d19c6dad8549e9c812fb2b7ce2105d7ff5

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

NOM DES PORTS D'ÉTAT CRÉÉS PAR COMMANDE D'IMAGE ID CONTENANT c3d6a9529fd7 test_again1.0 "bash" Il y a 2 secondes Jusqu'à 1 seconde awesome_haibt

Chaitra
la source
0

si vous souhaitez opérer sur le conteneur, vous devez l'exécuter au premier plan pour le maintenir en vie.

lwpro2
la source
-1

L'ordonnance d'argument est importante

La réponse de Jersey Beans (les 3 exemples) a fonctionné pour moi. Après pas mal de tâtonnements, j'ai réalisé que l'ordre des arguments importait.

Maintient le conteneur en cours d'exécution en arrière-plan: docker run -t -d <image-name>

Maintient le conteneur en cours d'exécution au premier plan: docker run <image-name> -t -d

Ce n'était pas évident pour moi venant d'un milieu Powershell.

HVL71
la source