2014-09-10 5 views
71

Ho visto un gruppo di tutorial che sembrano fare la stessa cosa che sto cercando di fare, ma per qualche motivo i miei contenitori Docker escono. Fondamentalmente, sto configurando un web server e alcuni daemon all'interno di un container Docker. Faccio le ultime parti di questo attraverso uno script di bash chiamato run-all.sh che eseguo tramite CMD nel mio Dockerfile. run-all.sh assomiglia a questo:Come mantenere il contenitore Docker in esecuzione dopo l'avvio dei servizi?

service supervisor start 
service nginx start 

E comincio all'interno del mio Dockerfile come segue:

CMD ["sh", "/root/credentialize_and_run.sh"] 

posso vedere che i servizi di tutte le start up in modo corretto quando si esegue le cose manualmente (ad esempio salire a l'immagine con -i -t/bin/bash), e tutto sembra funzionare correttamente quando eseguo l'immagine, ma termina quando termina l'avvio dei miei processi. Mi piacerebbe che i processi funzionassero a tempo indeterminato e, per quanto ho capito, il contenitore deve continuare a funzionare affinché ciò accada. Tuttavia, quando corro docker ps -a, vedo:

➜ docker_test docker ps -a 
CONTAINER ID  IMAGE       COMMAND    CREATED    STATUS      PORTS    NAMES 
c7706edc4189  some_name/some_repo:blah "sh /root/run-all.sh 8 minutes ago  Exited (0) 8 minutes ago      grave_jones 

cosa succede? Perché sta uscendo? So che potrei semplicemente mettere un ciclo while alla fine del mio script bash per tenerlo aggiornato, ma qual è il modo giusto per evitare che esca?

+1

stai esponendo le porte dei servizi all'esterno (opzione -p alla finestra mobile)? (ovviamente questo non impedirà loro di uscire) – ribamar

risposta

27

Non è proprio così che dovresti progettare i tuoi contenitori Docker.

Durante la progettazione di un contenitore Docker, si suppone di costruire in modo tale che v'è solo un processo in esecuzione (vale a dire si dovrebbe avere un contenitore per Nginx, e uno per supervisord o l'applicazione è in esecuzione); inoltre, quel processo dovrebbe essere eseguito in primo piano.

Il contenitore "si chiude" quando il processo stesso termina (nel tuo caso, tale processo è il tuo script di bash).


Tuttavia, se si davvero bisogno (o vogliono) di eseguire il servizio multiplo nel vostro contenitore Docker, prendere in considerazione a partire dal "Docker Base Image", che utilizza runit come un processo pseudo-init (runit rimarrà in linea mentre Nginx e Supervisor run), che rimarrà in primo piano mentre gli altri processi faranno il loro dovere.

Hanno documenti sostanziali, quindi dovresti essere in grado di ottenere ciò che stai cercando di fare abbastanza facilmente.

+0

Puoi spiegare perché dovrei avere un solo servizio in esecuzione? Potrei aggiungere nginx al supervisore se necessario, ma non sono sicuro del motivo per cui questo dovrebbe essere necessario. – Eli

+2

@Eli La risposta breve è che questo è il modo in cui Docker funziona. Docker esegue solo un processo (e i relativi figli) per contenitore. Si raccomanda che questo processo sia un processo di applicazione reale (in modo che se esce, Docker lo sa), ma in effetti si può usare il supervisore come tale processo. Si noti che è necessario configurare il supervisore per l'esecuzione in primo piano (ad esempio, non daemonize), operazione eseguita tramite l'opzione '--nodaemon'. –

+0

Non riesco a trovare la documentazione per essere incoraggiato a eseguire un solo servizio ovunque, e sembra strano. Che cosa succede se si desidera scaricare le credenziali per prime o eseguire alcuni script di avvio che devono essere eseguiti in fase di esecuzione? Puoi fornire un link al tuo reclamo? – Eli

9

Assicurarsi che si aggiunge daemon off; a voi nginx.conf o esegue con CMD ["nginx", "-g", "daemon off;"] come per l'immagine ufficiale nginx

Quindi utilizzare le seguenti operazioni per funzionare sia come supervisore servizio e nginx come processo in primo piano che impedirà il contenitore di uscire

service supervisor start && nginx

in alcuni casi sarà necessario avere più di un processo in un contenitore, in modo costringendo il contenitore di avere esattamente un processo non funziona e può creare più problemi di distribuzione.

Quindi è necessario comprendere i compromessi e prendere la decisione di conseguenza.

33

Il motivo per cui si chiude è perché lo script della shell viene eseguito prima come PID 1 e quando questo è completo, PID 1 è scomparso e la finestra mobile viene eseguita solo mentre PID 1 è.

È possibile utilizzare supervisore per fare tutto, se eseguito con il flag "-n" E 'detto di non demonizzare, in modo che rimarrà come il primo processo:

CMD ["/usr/bin/supervisord", "-n"] 

E la tua supervisord.conf:

[supervisord] 
nodaemon=true 

[program:startup] 
priority=1 
command=/root/credentialize_and_run.sh 
stdout_logfile=/var/log/supervisor/%(program_name)s.log 
stderr_logfile=/var/log/supervisor/%(program_name)s.log 
autorestart=false 
startsecs=0 

[program:nginx] 
priority=10 
command=nginx -g "daemon off;" 
stdout_logfile=/var/log/supervisor/nginx.log 
stderr_logfile=/var/log/supervisor/nginx.log 
autorestart=true 

Quindi è possibile avere tutti gli altri processi che si desidera e il supervisore gestirà il riavvio di essi, se necessario.

In questo modo è possibile utilizzare supervisord nei casi in cui potrebbe essere necessario nginx e php5-fpm e non ha molto senso separarli.

0

Ho lo stesso problem.You può provare questo comando: tronchi docker [container]

che vi mostrerà il motivo per cui il contenitore stop.In mio caso si vede: Permesso negato

42

Ho appena avuto lo stesso problema e ho scoperto che se si esegue il contenitore con il flag -t e -d, continua a essere in esecuzione.

docker run -td <image> 

Ecco quello che le bandiere fanno (secondo docker run --help):

-d, --detach=false   Run container in background and print container ID 
-t, --tty=false   Allocate a pseudo-TTY 

La più importante è la bandiera -t. -d ti consente solo di eseguire il contenitore in background.

+1

Non riesco a riprodurre questo. Per favore, fornire un esempio? C'è qualcosa di specifico (es .: CMD) su Dockerfile di cui abbiamo bisogno per far funzionare questo? –

+1

Questo non ha funzionato per me. Ho usato il comando 'registri docker ' per assicurarmi che si trattasse di un errore che causava l'uscita del mio contenitore docker. Lo stato di uscita è '0' e l'ultimo output è la confimazione che il mio' lighttpd'server è in esecuzione: '[ok] Avvio del web server: lighttpd. ' – ob1

+0

Non ho lavorato con Docker per un po 'di tempo. Quindi è possibile che l'interfaccia della riga di comando sia cambiata e che questo comando non funzioni più. –

24

basta usare tail -F -n0 /etc/hosts o qualcosa

non mancherà di tenere il vostro contenitore in esecuzione fino a quando non si fermano è

+0

in aggiunta alla mia risposta: ma comprendi che docker-compose (non demonizzato) viene utilizzato per mostrarti il ​​flusso di lavoro del tuo contenitore, quindi potrebbe essere utile per codificare i file di log dei servizi avviati. evviva –

+1

È un hack, ma funziona –

17

Se si utilizza un Dockerfile, provare:

ENTRYPOINT ["tail", "-f", "/dev/null"]

(Ovviamente questo è solo a scopo di sviluppo, non è necessario mantenere attivo un contenitore a meno che non stia eseguendo un processo, ad esempio nginx ...)

1

Cattura il PID del processo ngnix in una variabile (ad esempio $ NGNIX_PID) e alla fine del file entrypoint non

wait $NGNIX_PID 

In tal modo, il contenitore deve correre fino ngnix è vivo, quando ngnix si ferma, anche il container si ferma

Problemi correlati