2014-09-10 6 views
71

Widziałem kilka tutoriali, które wydają się robić to samo, co próbuję zrobić, ale z jakiegoś powodu moje kontenery Docker wyjść. Zasadniczo konfiguruję serwer WWW i kilka demonów w kontenerze Docker. Robię końcowe części tego poprzez skrypt bash o nazwie run-all.sh, który uruchamiam przez CMD w moim pliku Dockerfile. run-all.sh wygląda następująco:Jak przechowywać kontener Docker po uruchomieniu usług?

service supervisor start 
service nginx start 

i zaczynam go wewnątrz mojego Dockerfile następująco:

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

widzę, że usługi, wszystkie zaczynają się poprawnie, gdy uruchomię rzeczy ręcznie (tj wsiąść do obraz z opcją -i -t/bin/bash) i wszystko wygląda tak, jakby działało poprawnie po uruchomieniu obrazu, ale kończy się po zakończeniu uruchamiania moich procesów. Chciałbym, aby procesy były uruchamiane w nieskończoność i, o ile rozumiem, kontener musi działać, aby to się stało. Mimo to po uruchomieniu docker ps -a widzę:

➜ 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 

Co daje? Dlaczego to wychodzi? Wiem, że mogłem po prostu zatrzymać pętlę na końcu skryptu basha, żeby to utrzymać, ale jaki jest właściwy sposób, aby go nie wychodzić?

+1

czy wystawiasz porty usług na zewnątrz (opcja -p do dokowania)? (oczywiście nie przeszkadza im to wyjść) – ribamar

Odpowiedz

27

To nie jest tak, jak zaprojektować pojemniki Docker.

Przy projektowaniu pojemnik Docker, masz za zadanie budować to tak, że istnieje tylko jedenproces działa (tzn trzeba mieć jeden pojemnik na Nginx i jeden dla supervisord lub aplikacji to działa); dodatkowo proces ten powinien przebiegać na pierwszym planie.

Kontener zostanie "zakończony", gdy proces się zakończy (w twoim przypadku ten proces jest twoim skryptem basha).


Jeśli jednak naprawdę konieczności (lub chce) uruchamianie wielu usługę w pojemniku Docker rozważyć począwszy od "Docker Base Image", który wykorzystuje runit jako proces pseudo-init (runit pozostanie on-line podczas Nginx i Przebieg Supervisora), który pozostanie na pierwszym planie, podczas gdy inne procesy wykonają swoje zadanie.

Posiadają solidne dokumenty, więc powinieneś być w stanie osiągnąć to, co próbujesz zrobić w miarę łatwo.

+0

Czy możesz wyjaśnić, dlaczego powinienem mieć tylko jedną usługę? W razie potrzeby mogę dodać nginx do opiekuna, ale nie jestem pewien, dlaczego to powinno być konieczne. – Eli

+2

@ Eli Krótka odpowiedź brzmi, że tak działa Docker. Docker uruchomi tylko jeden proces (i jego dzieci) na kontener. Zaleca się, aby proces ten był rzeczywistym procesem aplikacji (tak, aby został zakończony, o czym Docker wie), ale w tym procesie rzeczywiście można użyć administratora. Zauważ, że będziesz musiał skonfigurować administratora, aby działał na pierwszym planie (tzn. Nie daemonize), co odbywa się za pomocą opcji '--nodaemon'. –

+0

Nie mogę znaleźć dokumentacji zachęcającej do uruchomienia tylko jednej usługi w dowolnym miejscu i wydaje się to dziwne. Co zrobić, jeśli chcesz najpierw pobrać referencje lub uruchomić skrypty startowe, które należy wykonać w czasie wykonywania? Czy możesz podać link do swojego roszczenia? – Eli

9

Upewnij się, że aby dodać daemon off; ty nginx.conf lub uruchomić go z CMD ["nginx", "-g", "daemon off;"] jak na oficjalnej nginx obrazu

Następnie użyj następujących uruchomić zarówno przełożonego jako usługa i nginx jako proces planie, który będzie zapobiegać pojemnik z wyjściem

service supervisor start && nginx

W niektórych przypadkach trzeba będzie mieć więcej niż jeden proces w kontenerze, więc zmusza pojemnik mieć dokładnie jeden proces nie będzie działać i może stworzyć więcej problemów w instalacji.

Musisz więc zrozumieć kompromisy i odpowiednio podjąć decyzję.

33

Powodem wyjścia jest to, że skrypt powłoki jest uruchamiany jako pierwszy PID 1, a gdy jest kompletny, PID 1 zniknął, a okno dokowane działa tylko podczas PID 1.

Można użyć przełożonego zrobić wszystko, jeśli uruchomić z „-n” flaga to powiedział nie daemonize, więc pozostanie jako pierwszego procesu:

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

i twój 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 

Następnie można wykonać dowolną liczbę procesów, a nadzorca zajmie się ich ponownym uruchomieniem w razie potrzeby.

W ten sposób możesz użyć nadzorcy w przypadkach, w których możesz potrzebować nginx i php5-fpm, i nie ma sensu ich rozdzielać.

0

mam takie same problem.You może spróbować tej komendy: kłody dokowane [kontener]

pokaże dlaczego pojemnik stop.In moim przypadku to pokazuje: Permission denied

42

Po prostu miałem ten sam problem i dowiedziałem się, że jeśli uruchamiasz swój pojemnik z flagą -t i -d, nadal działa.

docker run -td <image> 

Oto co zrobić flagi (według docker run --help):

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

Najważniejszy jest flaga -t. -d pozwala tylko uruchomić kontener w tle.

+1

Nie mogę tego odtworzyć. Czy mógłbyś podać przykład? Czy jest coś szczególnego (np .: CMD) o Dockerfile, którego potrzebujemy, aby to działało? –

+1

To nie działa dla mnie. Użyłem polecenia 'docker logs ', aby upewnić się, że był to błąd powodujący zamknięcie kontenera dokera. Status wyjścia to '0', a ostatnim wyjściem jest potwierdzenie, że mój serwer' lighttpd' działa: '[ok] Uruchomienie serwera WWW: lighttpd. ' – ob1

+0

Nie pracuję z Dockerem od dłuższego czasu. Jest więc możliwe, że interfejs wiersza poleceń został zmieniony i że to polecenie już nie działa. –

24

wystarczy użyć tail -F -n0 /etc/hosts lub coś

będzie utrzymać pojemnik działa tak długo, jak nie zatrzymać

+0

oprócz mojej odpowiedzi: ale rozumiem, że funkcja dokowania (nie daemonizowana) jest używana do wyświetlania przepływu pracy w twoim kontenerze, więc może być przydatne ogłaszanie plików dziennika twoich uruchomionych usług. Pozdrawiam –

+1

To jest hack, ale działa –

17

Jeśli używasz Dockerfile, spróbuj:

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

(Oczywiście jest to tylko dla celów programistycznych, nie powinieneś utrzymywać kontenera przy życiu, chyba że działa proces, np. Nginx ...)

1

Przechwytywanie PID procesu ngnix w zmiennej (na przykład $ NGNIX_PID) i na końcu pliku punkt_wejścia nie

wait $NGNIX_PID 

W ten sposób Twój pojemnik powinien działać aż ngnix żyje, kiedy ngnix zatrzymuje się, kontener zatrzymuje się również