Widziałem kilka samouczków, które wydają się robić to samo, co próbuję zrobić, ale z jakiegoś powodu moje kontenery Docker zamykają się. Zasadniczo konfiguruję serwer WWW i kilka demonów w kontenerze Dockera. run-all.sh
Wykonuję ostatnie części tego za pomocą skryptu bash o nazwie, który uruchamiam przez CMD w moim pliku Dockerfile. run-all.sh
wygląda tak:
service supervisor start
service nginx start
I uruchamiam go w moim pliku Docker w następujący sposób:
CMD ["sh", "/root/credentialize_and_run.sh"]
Widzę, że wszystkie usługi uruchamiają się poprawnie, gdy uruchamiam rzeczy ręcznie (tj. Wchodzę do obrazu za pomocą -i -t / bin / bash) i wszystko wygląda tak, jakby działało poprawnie po uruchomieniu obrazu, ale kończy się raz kończy uruchamianie moich procesów. Chciałbym, aby procesy działały w nieskończoność i, o ile rozumiem, kontener musi działać, aby tak się stało. Niemniej jednak, gdy biegnę 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 mógłbym po prostu umieścić pętlę while na końcu mojego skryptu bash, aby go utrzymać, ale jaki jest właściwy sposób, aby zapobiec jego zamknięciu?
Odpowiedzi:
Tak naprawdę nie należy projektować kontenerów Docker.
Projektując kontener Dockera, powinieneś zbudować go w taki sposób, aby działał tylko jeden proces (tj. Powinieneś mieć jeden kontener dla Nginx i jeden dla nadzorcy lub uruchomionej aplikacji); dodatkowo proces ten powinien przebiegać na pierwszym planie.
Kontener "wyjdzie" po zakończeniu samego procesu (w twoim przypadku tym procesem jest twój skrypt bash).
Jeśli jednak naprawdę potrzebujesz (lub chcesz) uruchomić wiele usług w swoim kontenerze Docker, rozważ rozpoczęcie od „Docker Base Image” , który jest używany
runit
jako proces pseudo-init (runit
pozostanie w trybie online podczas działania Nginx i Supervisor), który pozostanie na pierwszym planie, podczas gdy inne procesy robią swoje.Mają pokaźną dokumentację, więc powinieneś być w stanie osiągnąć to, co próbujesz zrobić, w miarę łatwo.
źródło
--nodaemon
opcji.Jeśli używasz pliku Dockerfile, spróbuj:
(Oczywiście jest to tylko do celów deweloperskich, nie powinno być konieczne utrzymywanie kontenera przy życiu, chyba że działa w nim proces, np. Nginx ...)
źródło
CMD["sleep", "1d"]
ale rozwiązanie wydaje się lepszeCMD["sleep", "infinity"]
.exec tail -f /dev/null
ale użycie gotail
jako punktu wejścia jest błędną odpowiedzią.Po prostu miałem ten sam problem i odkryłem, że jeśli używasz swojego kontenera z flagą
-t
i-d
, to nadal działa.Oto, co robią flagi (według
docker run --help
):Najważniejszym z nich jest
-t
flaga.-d
po prostu pozwala uruchomić kontener w tle.źródło
docker logs <image>
aby upewnić się, że to błąd, który powoduje zamknięcie mojego kontenera Docker. Status wyjścia to,0
a ostatnie wyjście to potwierdzenie, że mójlighttpd
serwer działa:[ ok ] Starting web server: lighttpd.
exec bash
lubexec sh
jeśli bash nie jest zainstalowany, do końca start.sh. Następnie możesz użyć flagi -tPrzyczyną zakończenia jest to, że skrypt powłoki jest uruchamiany jako pierwszy jako PID 1, a po zakończeniu PID 1 znika, a docker działa tylko wtedy, gdy PID 1 jest.
Możesz użyć przełożonego do zrobienia wszystkiego, jeśli zostanie uruchomiony z flagą „-n”, powiedziano mu, aby nie demonizował, więc pozostanie jako pierwszy proces:
I twój supervisord.conf:
Wtedy możesz mieć tyle innych procesów, ile chcesz, a przełożony zajmie się ich ponownym uruchomieniem, jeśli zajdzie taka potrzeba.
W ten sposób możesz użyć supervisord w przypadkach, w których możesz potrzebować nginx i php5-fpm i nie ma sensu ich rozdzielać.
źródło
If the "init" process of a PID namespace terminates, the kernel terminates all of the processes in the namespace via a SIGKILL signal. This behavior reflects the fact that the "init" process is essential for the correct operation of a PID namespace.
możesz działać
cat
bez żadnych argumentów, jak wspomniał bro @ Sa'ad, aby po prostu utrzymać działający kontener [właściwie nie robiąc nic poza czekaniem na dane wejściowe użytkownika] (wtyczka Jenkinsa Docker robi to samo)źródło
cat
. jenkin's Docker plugin robi to.Upewnij się, że dodajesz
daemon off;
do siebie plik nginx.conf lub uruchom goCMD ["nginx", "-g", "daemon off;"]
zgodnie z oficjalnym obrazem nginxNastępnie użyj poniższego, aby uruchomić zarówno nadzorcę jako usługę, jak i nginx jako proces pierwszego planu, który zapobiegnie zamknięciu kontenera
service supervisor start && nginx
W niektórych przypadkach będziesz musiał mieć więcej niż jeden proces w swoim kontenerze, więc wymuszenie, aby kontener miał dokładnie jeden proces, nie zadziała i może spowodować więcej problemów podczas wdrażania.
Musisz więc zrozumieć kompromisy i podjąć odpowiednią decyzję.
źródło
Motywacja:
Nie ma nic złego w uruchamianiu wielu procesów w kontenerze Dockera . Jeśli ktoś lubi używać dockera jako lekkiej maszyny wirtualnej - niech tak będzie. Inni lubią dzielić swoje aplikacje na mikrousługi. Ja myślę: stos LAMP w jednym pojemniku? Po prostu świetnie.
Odpowiedź:
Trzymaj się dobrego obrazu podstawowego, takiego jak obraz podstawowy fuzji . Mogą być inni. Proszę skomentuj.
A to tylko kolejna prośba o przełożonego. Ponieważ obraz bazowy phusion zapewnia nadzorcę oprócz kilku innych rzeczy, takich jak cron i konfiguracja ustawień regionalnych. Rzeczy, które lubisz mieć konfigurację podczas uruchamiania tak lekkiej maszyny wirtualnej. Na co warto zwrócić uwagę, zapewnia również połączenia ssh do kontenera.
Sam obraz phusion po prostu się uruchomi i będzie działał, jeśli wydasz tę podstawową instrukcję uruchamiania dockera:
Lub banalnie proste:
Jeśli obraz podstawowy nie jest dla ciebie ... Aby szybki CMD mógł go uruchomić, przypuszczałbym coś takiego dla basha:
Lub to dla busybox:
To jest miłe, ponieważ wyjdzie natychmiast na
docker stop
. Po prostu zwykłysleep
lubcat
potrwa kilka sekund, zanim kontener zostanie zamknięty.źródło
Przechwyć PID procesu ngnix w zmiennej (na przykład $ NGNIX_PID) i na końcu pliku punktu wejścia wykonaj
W ten sposób twój kontener powinien działać, dopóki ngnix nie będzie żył, kiedy ngnix się zatrzyma, kontener również się zatrzyma
źródło
Co powiesz na skorzystanie z nadzorowanej formy usługi, jeśli jest dostępna?
usługa YOUR_SERVICE nadzoruje
Oszczędza konieczność tworzenia pliku
supervisord.conf
źródło