Dlaczego nie mogę wielokrotnie używać platformy Docker CMD do uruchamiania wielu usług?

98

Zbudowałem podstawowy obraz z Dockerfile o nazwie centos + ssh. W Dockerfile centos + ssh używam CMD do uruchamiania usługi ssh.

Następnie chcę zbudować obraz i uruchomić inną usługę o nazwie rabbitmq, plik Dockerfile:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD /opt/mq/sbin/rabbitmq-server start

Aby uruchomić pojemnik RabbitMQ , Uruchom :

docker run -d -p 222:22 -p 4149:4149 rabbitmq

ale usługa ssh nie działa, wyczuwa, że ​​plik CMD rabbitmq zastępuje CMD centos.

  1. Jak działa CMD w obrazie dockera?
  2. Jeśli chcę uruchomić wiele usług, jak to zrobić? Korzystasz z przełożonego?
edwardsbean
źródło

Odpowiedzi:

64

Mimo że CMD jest zapisany w pliku Dockerfile, tak naprawdę jest to informacja o czasie wykonywania. Podobnie jak EXPOSE, ale w przeciwieństwie do np. RUN i ADD. Rozumiem przez to, że możesz to zmienić później, w rozszerzającym się pliku Dockerfile lub po prostu w poleceniu uruchamiania, czego doświadczasz. Przez cały czas może istnieć tylko jeden CMD.

Jeśli chcesz uruchomić wiele usług, rzeczywiście użyłbym przełożonego. Możesz utworzyć plik konfiguracyjny nadzorcy dla każdej usługi, dodać je do katalogu i uruchomić nadzorcę, supervisord -c /etc/supervisoraby wskazał plik konfiguracyjny nadzorcy, który ładuje wszystkie twoje usługi i wygląda jak

[supervisord]
nodaemon=true

[include]
files = /etc/supervisor/conf.d/*.conf

Jeśli chcesz uzyskać więcej informacji, napisałem bloga na ten temat tutaj: http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image- dziedzictwo/

qkrijger
źródło
Dzięki, kierownik to dobry pomysł, ale zastanawiam się, jak działa CMD w obrazie
dockera
2
Zadałeś dwa pytania, 2. dotyczące obsługi wielu usług. Zastanawiając się, jak działa CMD, opisz szczegółowo, co chcesz wiedzieć. Wspomniałem już, że jest to informacja o czasie wykonywania i nadpisanie przez dowolny nowy CMD.
qkrijger
119

Masz rację, drugi plik Dockerfile nadpisze CMDpolecenie pierwszego. Docker zawsze uruchamia jedno polecenie, nie więcej. Na końcu pliku Dockerfile możesz określić jedno polecenie do uruchomienia. Nie więcej.

Ale możesz wykonać oba polecenia w jednej linii:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD service sshd start && /opt/mq/sbin/rabbitmq-server start

Co możesz również zrobić, aby uczynić plik Dockerfile nieco czystszym, możesz umieścić swoje polecenia CMD w dodatkowym pliku:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD sh /home/centos/all_your_commands.sh

I taki plik:

service sshd start &
/opt/mq/sbin/rabbitmq-server start
Thomas Uhrig
źródło
1
dzięki, myślę, że użyj menedżera jest lepszy. ale dlaczego docker uruchamia tylko jeden CMD? co się dzieje w środku?
edwardsbean
1
Nie wiem, co się dzieje w środku. Ale myślę, że jest po prostu tak zaprojektowany. Kiedy masz obraz i uruchomisz w nim polecenie (np. Z CMD), uruchamia kontener. Kontener działa tak długo, jak działa polecenie. Gdy tylko polecenie zakończy się, kontener również się zatrzyma. Zatem każdy kontener reprezentuje jedno (uruchomione) polecenie.
Thomas Uhrig
Myślę, że może to z powodu lcx lub czegoś w rodzaju limitu
edwardsbean
2
@ Tyguy7 .. ponieważ ................?
StartupGuy
1
&&technika zadziała tylko z usługami nieinteraktywnymi (które mogą być uruchamiane w tle), w przeciwnym razie tylko pierwsza będzie działać.
noraj
27

Chociaż szanuję odpowiedź qkrijgera wyjaśniającą, jak możesz obejść ten problem, myślę, że możemy dowiedzieć się o wiele więcej o tym, co się tutaj dzieje ...

Aby właściwie odpowiedzieć na pytanie „ dlaczego ” ... Myślę, że byłoby pomocne, gdybyś zrozumiał, jak docker stopdziała polecenie i że wszystkie procesy powinny być zamykane w sposób czysty, aby zapobiec problemom podczas próby ich ponownego uruchomienia (uszkodzenie plików itp.).

Problem: Co zrobić, jeśli doker zrobił startu SSH od jego polecenia i zaczął RabbitMQ z pliku Docker? „ Polecenie docker stop próbuje najpierw zatrzymać działający kontener, wysyłając sygnał SIGTERM do procesu głównego (PID 1) w kontenerze. Który proces jest śledzony przez docker jako PID 1, który otrzyma SIGTERM? Czy to będzie SSH czy Rabbit ?? „Zgodnie z modelem procesu Unix, proces inicjowania - PID 1 - dziedziczy wszystkie osierocone procesy potomne i musi je zbierać. Większość kontenerów Dockera nie ma procesu inicjującego, który robi to poprawnie, w wyniku czego ich kontenery są zapełniane procesy zombie w czasie ”.

Odpowiedź: Docker prostu wykonuje tę ostatnią CMD jako jeden z nich dostanie uruchomiony jako proces korzenia z PID 1 i uzyskać od SIGTERM docker stop.

Sugerowane rozwiązanie: Powinieneś użyć (lub utworzyć) obraz podstawowy przeznaczony specjalnie do uruchamiania więcej niż jednej usługi, takiej jak phusion / baseimage

Należy zauważyć, że tini istnieje właśnie z tego powodu, a od wersji Docker 1.13 i nowszych tini jest oficjalnie częścią Dockera, co oznacza, że ​​uruchomienie więcej niż jednego procesu w Dockerze JEST PRAWIDŁOWE ... więc nawet jeśli ktoś twierdzi, że Miej większe umiejętności w zakresie Dockera i nalega, abyś myślał o tym absurdalnie, wiedz, że tak nie jest. Istnieją całkowicie uzasadnione sytuacje, w których można to zrobić.

Dobrze wiedzieć:

StartupGuy
źródło
3

Oficjalna odpowiedź Dockera na uruchamianie wielu usług w kontenerze .

Wyjaśnia, jak można to zrobić za pomocą systemu init (systemd, sysvinit, upstart), skryptu ( CMD ./my_wrapper_script.sh) lub nadzorcy, takiego jak supervisord.

&&Obejście może pracować tylko dla usług, które rozpoczyna się w tle (demonów) lub że będzie wykonać szybko, bez interakcji i zwolnić polecenia. Robi to z usługą interaktywną (która zachowuje monit) i tylko pierwsza usługa zostanie uruchomiona.

noraj
źródło
0

Aby wyjaśnić, dlaczego CMD jest zaprojektowany do uruchamiania tylko jednej usługi na kontener, uświadommy sobie, co by się stało, gdyby serwery pomocnicze działające w tym samym kontenerze nie były trywialne / pomocnicze, ale „główne” (np. Pamięć masowa w pakiecie z aplikacją frontend). Na początek zepsuje kilka ważnych funkcji kontenerowania, takich jak (automatyczne) skalowanie poziome i zmiana harmonogramu między węzłami, z których oba zakładają, że istnieje tylko jedna aplikacja (źródło obciążenia procesora) na kontener. Następnie pojawia się kwestia podatności - więcej serwerów ujawnionych w kontenerze to częstsze łatanie CVE ...

Przyznajmy więc, że jest to „popychanie” projektantów Dockera (i Kubernetes / Openshift) w kierunku dobrych praktyk i nie powinniśmy wymyślać na nowo obejść (SSH nie jest konieczne - docker exec / kubectl exec / oc rshzaprojektowaliśmy go, aby go zastąpić).

  • Więcej informacji

/devops/447/why-it-is-recommended-to-run-only-one-process-in-a-container

mirekphd
źródło