Perché il contenitore docker esce immediatamente


240

Eseguo un contenitore in background utilizzando

 docker run -d --name hadoop h_Service

esce rapidamente. Ma se corro in primo piano, funziona benissimo. Ho controllato i log usando

docker logs hadoop

non c'è stato nessun errore. Qualche idea?

DOCKERFILE

 FROM java_ubuntu_new
 RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
 RUN dpkg -i cdh4-repository_1.0_all.deb
 RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
 RUN  apt-get update
 RUN apt-get install -y hadoop-0.20-conf-pseudo
 RUN dpkg -L hadoop-0.20-conf-pseudo
 USER hdfs
 RUN hdfs namenode -format
 USER root
 RUN apt-get install -y sudo
 ADD . /usr/local/
 RUN chmod 777 /usr/local/start-all.sh
 CMD ["/usr/local/start-all.sh"]

start-all.sh

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start
 /etc/init.d/hadoop-hdfs-datanode start
 /etc/init.d/hadoop-hdfs-secondarynamenode start
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start
 /bin/bash

1
La regola d'oro è che dovresti impedire ai tuoi server docker di eseguire la demonizzazione. La maggior parte dei pacchetti server ha opzioni per forzarli in primo piano poiché il demonizzazione è il caso normale.
Arnaud Meuret,

Qualunque cosa tu stia sperando di realizzare, chmod 777è insicuro e sbagliato. Dovresti ripristinare le autorizzazioni sane (probabilmente 755 in questo caso).
Tripleee

Risposte:


125

Un container docker viene chiuso al termine del processo principale.

In questo caso, verrà chiuso al start-all.shtermine dello script. Non ho abbastanza informazioni su hadoop per dirti come farlo in questo caso, ma devi eseguire qualcosa in primo piano o utilizzare un gestore di processi come runit o supervisord per eseguire i processi.

Penso che ti sbagli se funziona se non lo specifichi -d; dovrebbe avere esattamente lo stesso effetto. Ho il sospetto che tu l'abbia lanciato con un comando leggermente diverso o usando -itquale cambierà le cose.

Una soluzione semplice potrebbe essere quella di aggiungere qualcosa di simile:

while true; do sleep 1000; done

fino alla fine della sceneggiatura. Non mi piace tuttavia, poiché lo script dovrebbe davvero monitorare i processi che ha dato il via.

(Dovrei dire che ho rubato quel codice da https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh )


218

Questo ha fatto il trucco per me:

docker run -dit ubuntu

Dopo di ciò, ho verificato i processi in esecuzione utilizzando:

docker ps -a

Per fissare nuovamente il contenitore

docker attach CONTAINER_NAME

SUGGERIMENTO: per uscire senza arrestare il tipo di contenitore: ^P^Q


15
@Tommy, da docs.docker.com/engine/reference/commandline/run -d, --detach Modalità indipendente: esegui il comando in background, -i, --interactive Mantieni STDIN aperto anche se non collegato, -t, - -tty Allocare uno pseudo-TTY -ditè solo una scorciatoia

3
@ am17torres, scusami, lasciami chiarire la mia domanda confusa; d è staccato e io sono interattivo, quindi la combinazione di d e io mi confonde. Ho pensato che l'avrebbe lanciato come processo in background (non interattivo).
Tommy,

2
@ Tommy Quando queste opzioni vengono combinate, il contenitore entra in modalità interattiva in background .
Sì,

2
@ Tommy, @ am17torres -diè il minimo richiesto, l' -topzione è ridondante se usata con -dse ho capito bene
Renaud,

2
In realtà non sarai in grado di vedere il tuo prompt se ricolleghi senza -tabilitato ... ma dal momento che di solito execun nuovo bash ogni volta che non lo noto. Ho avuto problemi a staccarmi da un mac ma forse sto sbagliando ...
Renaud,

65

Vorrei estendere o osare dire, migliorare la risposta menzionata da Camposer

Quando corri

docker run -dit ubuntu

stai fondamentalmente eseguendo il container in background in modalità interattiva.

Quando si collega e si esce dal contenitore con CTRL + D (il modo più comune per farlo), si interrompe il contenitore perché è stato appena terminato il processo principale con cui è stato avviato il contenitore con il comando precedente.

Approfittando di un contenitore già in esecuzione, vorrei solo fork un altro processo di bash e ottenere uno pseudo TTY eseguendo:

docker exec -it <container ID> /bin/bash

29

ogni volta che voglio che un contenitore rimanga attivo dopo aver terminato l'esecuzione dello script, aggiungo

&& tail -f /dev/null

alla fine del comando. Quindi dovrebbe essere:

/usr/local/start-all.sh && tail -f /dev/null

19

Perché il contenitore docker esce immediatamente?

Se si desidera forzare l'immagine in sospeso (per eseguire il debug di qualcosa o esaminare lo stato del file system) è possibile ignorare il punto di ingresso per cambiarlo in una shell:

docker run -it --entrypoint=/bin/bash myimagename

18

Un buon approccio sarebbe quello di avviare i processi e i servizi eseguendoli in background e utilizzare il wait [n ...]comando alla fine dello script. In bash, il comando wait impone al processo corrente di:

Attendere ogni processo specificato e restituire lo stato di terminazione. Se non viene specificato n, vengono attesi tutti i processi figlio attualmente attivi e lo stato di restituzione è zero.

Ho avuto questa idea dalla sceneggiatura iniziale di Sébastien Pujadas per la sua build alce .

Prendendo dalla domanda originale, start-all.sh sarebbe simile a questo ...

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start &
 /etc/init.d/hadoop-hdfs-datanode start &
 /etc/init.d/hadoop-hdfs-secondarynamenode start &
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
 wait

5

Aggiungi questo alla fine di Dockerfile:

CMD tail -f /dev/null

File Docker di esempio:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null

Riferimento


CMD tail -f /dev/nulllo attraversa sh -c "...". Possiamo execinvece usare il modulo? Vale a direCMD ["tail", "-f", "/dev/null"]
Meglio

4

La mia pratica è nel Dockerfile avviare una shell che non uscirà immediatamente CMD [ "sh", "-c", "service ssh start; bash"], quindi eseguire docker run -dit image_name. In questo modo il servizio (ssh) e il contenitore sono attivi.


1

Ho aggiunto l' readistruzione shell alla fine. Ciò mantiene in esecuzione il processo principale del container - startup shell script.


1

Aggiunta

exec "$@"

alla fine del mio script shell era la mia soluzione!


Ciò significa solo che eseguirà il tuo cmd, se il tuo cmd è solo 'bash', allora non funzionerà ancora
Shardj

1

Se si controlla Dockerfile dai contenitori, ad esempio fballiano / magento2-apache-php

vedrai che alla fine del suo file aggiunge il seguente comando: while true; dormire 1; fatto

Ora, ciò che raccomando è che tu lo faccia

docker container ls --all | grep 127

Quindi, vedrai se l'immagine della finestra mobile ha avuto un errore, se esce con 0, probabilmente avrà bisogno di uno di questi comandi che dormirà per sempre.


0

Esistono molti modi possibili per far uscire immediatamente una finestra mobile. Per me, era il problema con il mio Dockerfile. Si è verificato un errore in quel file. Ho avuto ENTRYPOINT ["dotnet", "M4Movie_Api.dll]invece di ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]. Come puoi vedere, alla fine avevo perso una citazione (").

Per analizzare il problema ho avviato il mio contenitore e attaccato rapidamente il mio contenitore in modo da poter vedere qual era il problema esatto.

C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b


C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b

Dove 4ea373efa21b è il mio ID contenitore. Questo mi porta al vero problema.

inserisci qui la descrizione dell'immagine

Dopo aver riscontrato il problema, ho dovuto creare, ripristinare, pubblicare nuovamente il mio contenitore.


0

Provenendo da duplicati, non vedo alcuna risposta qui che affronti l'antipasto molto comune dell'esecuzione del carico di lavoro principale come lavoro in background e poi mi chiedo perché esca Docker.

In termini semplici, se lo hai

my-main-thing &

quindi estrarre il &per eseguire il lavoro in primo piano o aggiungere

wait

alla fine dello script per farlo attendere tutti i processi in background.

Quindi uscirà comunque se il carico di lavoro principale viene while truechiuso , quindi forse eseguirlo in un ciclo per forzarlo a riavviarsi per sempre:

while true; do
    my-main-thing &
    other things which need to happen while the main workload runs in the background
    maybe if you have such things
    wait
done

(Nota anche come scrivere while true. È comune vedere cose stupide come while [ true ]o while [ 1 ]che per coincidenza funzionano, ma non significano ciò che l'autore probabilmente immaginava che avrebbero dovuto significare.)


0

È necessario eseguirlo con -d flag per lasciarlo in esecuzione come daemon in background.

docker run -d -it ubuntu bash


-5

È possibile eseguire il contenitore usando questo flag di riavvio.

docker run -d --name=<some-name> -p xxxx:xxxx ... <image-name> --restart=unless-stopped

-8

Poiché l'immagine è un linux, una cosa da verificare è assicurarsi che tutti gli script di shell utilizzati nel contenitore abbiano terminazioni di riga unix. Se hanno una ^ M alla fine, allora sono terminazioni di linea di Windows. Un modo per risolverli è con dos2unix su /usr/local/start-all.sh per convertirli da Windows in Unix. L'esecuzione della finestra mobile in modalità interattiva può aiutare a capire altri problemi. Si potrebbe avere un refuso o qualcosa del nome del file. vedi https://en.wikipedia.org/wiki/Newline

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.