Dlaczego kontener dokerów natychmiast się kończy

239

Korzystam z kontenera w tle, używając

 docker run -d --name hadoop h_Service

wychodzi szybko. Ale jeśli uruchomię się na pierwszym planie, działa dobrze. Sprawdziłem dzienniki za pomocą

docker logs hadoop

nie było błędu. Jakieś pomysły?

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
Gibbs
źródło
1
Złota zasada polega na tym, że należy zapobiegać demonizacji serwerów dokowanych. Większość pakietów serwerów ma opcje wymuszenia ich na pierwszym planie, ponieważ demonizacja jest normalnym przypadkiem.
Arnaud Meuret
Cokolwiek masz nadzieję osiągnąć, chmod 777jest niepewne i złe. Powinieneś powrócić do rozsądnych uprawnień (prawdopodobnie 755 w tym przypadku).
tripleee,

Odpowiedzi:

125

Kontener dokera kończy pracę po zakończeniu głównego procesu.

W takim przypadku zakończy działanie po start-all.shzakończeniu skryptu. Nie wiem wystarczająco dużo o hadoopie, aby powiedzieć ci, jak to zrobić w tym przypadku, ale musisz albo zostawić coś uruchomionego na pierwszym planie, albo użyć menedżera procesów, takiego jak runit lub supervisord, aby uruchomić procesy.

Myślę, że musisz się mylić, że działa, jeśli nie określisz -d; powinien mieć dokładnie taki sam efekt. Podejrzewam, że uruchomiłeś go za pomocą nieco innej komendy lub użycia, -itktóre zmieni rzeczy.

Prostym rozwiązaniem może być dodanie czegoś takiego:

while true; do sleep 1000; done

do końca skryptu. Nie podoba mi się to, ponieważ skrypt powinien naprawdę monitorować procesy, które rozpoczął.

(Powinienem powiedzieć, że ukradłem ten kod z https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh )

Adrian Mouat
źródło
217

To załatwiło sprawę:

docker run -dit ubuntu

Następnie sprawdziłem, czy procesy działają, używając:

docker ps -a

Do ponownego zamocowania pojemnika

docker attach CONTAINER_NAME

WSKAZÓWKA: Aby wyjść bez zatrzymywania typu kontenera: ^P^Q

Camposer
źródło
15
@ Tommy, z docs.docker.com/engine/reference/commandline/run -d, --detach Tryb odłączony: uruchom polecenie w tle, -i, --interactive Pozostaw STDIN otwarty, nawet jeśli nie jest dołączony, -t, - -tty Przydziel pseudo-TTY -ditjest tylko skrótem
3
@ am17torres racja, przepraszam, pozwól mi wyjaśnić moje mylące pytanie; d jest odłączony, a ja interaktywny, więc kombinacja di i jest dla mnie myląca. Myślałem, że d ma uruchomić go jako proces tła (nieinteraktywny).
Tommy
2
@ Tommy Po połączeniu tych opcji pojemnik przejdzie w tryb interaktywny w tle .
Wrz
2
@Tommy, @ am17torres -dijest wymaganym minimum, -topcja jest zbędna, jeśli jest używana, -djeśli dobrze rozumiem
Renaud
2
W rzeczywistości nie zobaczysz swojego monitu, jeśli ponownie połączysz się bez -twłączonego ... ale ponieważ zwykle jestem execnowy bash za każdym razem, gdy tego nie zauważam. Miałem problemy z odłączeniem się od komputera Mac, ale może robię to źle ...
Renaud
65

Chciałbym przedłużyć, czy ośmielę się powiedzieć, poprawić odpowiedź, o której wspomina Camposer

Kiedy biegniesz

docker run -dit ubuntu

w zasadzie uruchamiasz kontener w tle w trybie interaktywnym.

Po dołączeniu i zamknięciu kontenera za pomocą CTRL + D (najczęstszy sposób, aby to zrobić), zatrzymujesz kontener, ponieważ właśnie zabiłeś główny proces, który uruchomiłeś kontener za pomocą powyższego polecenia.

Korzystając z już działającego kontenera, po prostu rozwidlę kolejny proces bash i otrzymam pseudo TTY, uruchamiając:

docker exec -it <container ID> /bin/bash
Krishna Gupta
źródło
29

za każdym razem, gdy chcę, aby kontener pozostał bezczynny po zakończeniu wykonywania skryptu, dodaję

&& tail -f /dev/null

na końcu polecenia. Tak powinno być:

/usr/local/start-all.sh && tail -f /dev/null
Thiago Ramos
źródło
19

Dlaczego kontener dokerów natychmiast wychodzi?

Jeśli chcesz zmusić obraz do zawieszenia się (w celu debugowania lub sprawdzenia stanu systemu plików), możesz zastąpić punkt wejścia, aby zmienić go na powłokę:

docker run -it --entrypoint=/bin/bash myimagename
RJFalconer
źródło
18

Dobrym podejściem byłoby uruchomienie procesów i usług, uruchamiając je w tle i używając wait [n ...]polecenia na końcu skryptu. W bash polecenie czekania wymusza na bieżącym procesie:

Poczekaj na każdy określony proces i zwróć jego status zakończenia. Jeśli nie podano n, wszystkie aktualnie aktywne procesy potomne są czekane, a zwracany status wynosi zero.

Wpadłem na ten pomysł ze skryptu startowego Sébastiena Pujadasa dla jego budowy łosi .

Biorąc z pierwotnego pytania, twoja strona start-all.sh wyglądałaby mniej więcej tak ...

 #!/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
Brian Olsen
źródło
5

Dodaj to na końcu Dockerfile:

CMD tail -f /dev/null

Przykładowy plik Docker:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null

Odniesienie

Kert Kukk
źródło
CMD tail -f /dev/nulluruchamia to sh -c "...". Czy execzamiast tego możemy użyć formularza? To znaczyCMD ["tail", "-f", "/dev/null"]
Meglio
4

Moja praktyka polega na tym, że w Dockerfile uruchom powłokę, która nie wyjdzie natychmiast CMD [ "sh", "-c", "service ssh start; bash"], a następnie uruchom docker run -dit image_name. W ten sposób usługa (ssh) i kontener są uruchomione.

Leon
źródło
1

Na końcu dodałem readinstrukcję powłoki. Dzięki temu główny proces kontenera - skrypt powłoki startowej - działa.

Jaydeep Ranipa
źródło
1

Dodawanie

exec "$@"

na końcu mojego skryptu powłoki była moja poprawka!

Adam K.
źródło
Oznacza to tylko, że uruchomi twoje cmd, jeśli twoje cmd to tylko „bash”, to i tak nie zadziała
Shardj
1

Jeśli sprawdzisz plik Dockerfile z kontenerów, na przykład fballiano / magento2-apache-php

zobaczysz, że na końcu swojego pliku dodaje następujące polecenie: while true; śpij 1; Gotowe

Teraz polecam, abyś to zrobił

docker container ls --all | grep 127

Następnie zobaczysz, czy w obrazie dokera wystąpił błąd, jeśli zakończy się na 0, prawdopodobnie potrzebuje jednego z tych poleceń, które będą spać na zawsze.

Xavierbaez
źródło
0

Istnieje wiele możliwych sposobów natychmiastowego wyjścia dokera. Dla mnie to był problem z moim Dockerfile. W tym pliku wystąpił błąd. Miałem ENTRYPOINT ["dotnet", "M4Movie_Api.dll]zamiast ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]. Jak widać, na końcu przeoczyłem jeden cytat („).

Aby przeanalizować problem, uruchomiłem swój pojemnik i szybko podłączyłem go, aby zobaczyć, jaki jest dokładnie problem.

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


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

Gdzie 4ea373efa21b to mój identyfikator kontenera. To prowadzi mnie do faktycznego problemu.

wprowadź opis zdjęcia tutaj

Po znalezieniu problemu musiałem ponownie zbudować, przywrócić, opublikować mój kontener.

Sibeesh Venu
źródło
0

Pochodząc z duplikatów, nie widzę tutaj żadnej odpowiedzi, która dotyczyłaby bardzo powszechnego przeciwwskazania uruchamiania głównego obciążenia pracą jako zadania w tle, a następnie zastanawiania się, dlaczego Docker kończy pracę.

W prostych słowach, jeśli masz

my-main-thing &

następnie albo wyjmij, &aby uruchomić zadanie na pierwszym planie, albo dodaj

wait

na końcu skryptu, aby czekał na wszystkie zadania w tle.

Następnie nadal zakończy pracę, jeśli główne obciążenie zostanie zakończone, więc może uruchom to w while truepętli, aby zmusić go do ponownego uruchomienia na zawsze:

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

(Zauważmy też, jak pisać while true. To wspólne, aby zobaczyć jak głupie rzeczy while [ true ]lub while [ 1 ]które przypadkowo zdarzyć do pracy, ale nie oznacza to, co autor zapewne wyobrażał powinni rozumieć).

potrójny
źródło
0

Musisz uruchomić go z opcją -d, aby działał jako demon w tle.

docker uruchom -d -it ubuntu bash

Vivek
źródło
-5

Możesz uruchomić kontener za pomocą tej flagi restartu.

docker run -d --name=<some-name> -p xxxx:xxxx ... <image-name> --restart=unless-stopped
Akmal Ahmed
źródło
-8

Ponieważ obraz jest linuksem, należy sprawdzić, czy wszystkie skrypty powłoki używane w kontenerze mają zakończenia linii unixowych. Jeśli mają na końcu ^ M, to są zakończeniami linii systemu Windows. Jednym ze sposobów, aby je naprawić, jest dos2unix na /usr/local/start-all.sh, aby przekonwertować je z systemu Windows na unix. Uruchomienie dokera w trybie interaktywnym może pomóc rozwiązać inne problemy. Możesz mieć literówkę nazwy pliku lub coś takiego. patrz https://en.wikipedia.org/wiki/Newline

dskow
źródło