Jak wykryć, czy uruchomienie dockera powiodło się programowo?

83

Piszę bardzo prosty skrypt bash, aby szybko sprawdzić, czy mój kontener nadal buduje się i uruchamia poprawnie oraz czy aplikacja w środku odpowiada na żądania.

Czasami docker runkończy się to niepowodzeniem, np. Ponieważ port, z którym próbuję powiązać kontener, jest już przydzielony. Ale kiedy to się dzieje docker run, kod zakończenia nadal wynosi 0, więc nie mogę użyć kodu zakończenia. Jak mogę programowo sprawdzić, czy kontener został uruchomiony poprawnie?

Rozważane przeze mnie rozwiązania to:

  • analizuje dane wyjściowe pod kątem błędów
  • docker ps aby sprawdzić, czy kontener jest uruchomiony

ale oba wydają się trochę przesadzone i brzydkie. Czy brakuje mi lepszego sposobu na sprawdzenie, czy się docker runudało?

Jules Olléon
źródło
1
Nie jestem pewien, na czym polega problem. Jeśli dany proces zachowuje się w zwykły sposób, możesz po prostu sprawdzić kod zakończenia. Jeśli emituje kod zakończenia równy 0 nawet w przypadku nieudanych przypadków, spróbuj dowiedzieć się, czy jest to błąd. Jeśli w jakimkolwiek przypadku program zwraca kod zakończenia równy 0, prawdopodobnie nie pozostaje Ci nic innego, jak tylko przeanalizować dane wyjściowe.
devnull
Jak @devnull powiedział, jeśli nie można ufać, że docker runzwróci niezerowy kod powrotny w przypadku niepowodzenia, jak wskazują to wszystko można zrobić, to analizować dane wyjściowe (co może być skomplikowane lub kruche) lub użyć innego polecenia (czyli swoją pssugestię ), aby sprawdzić wynik pierwszego polecenia. Możesz rozważyć wypełnienie zgłoszenia w dockerze, aby sprawdzić, czy mogą również naprawić kod powrotu run.
Etan Reisner,
Upewnij się, że masz najnowszą wersję.
ooga,
Czy to niestandardowy kod uruchamiany w Twoim kontenerze? jeśli tak, możesz wyeksportować port w swoim pliku Dockerfile, a gdy program jest stabilnie uruchomiony, wyślij komunikat „OK” na tym porcie. Twój kod klienta czeka na komunikat „OK”.
rexposadas
3
Czy możesz podać przykład, jak używasz dockera i której wersji? Szybki test pokazuje, że dla mnie kod zakończenia Dockera to 1docker run -d -p 9010:9010 busybox true ; echo $?
Abel Muiño.

Odpowiedzi:

118

Jak zasugerował Abel Muiño w komentarzach, mogło to zostać naprawione w nowszych wersjach Dockera (obecnie używam 0.9.1).

Ale jeśli tymczasowo utkniesz tak jak ja ze starszą wersją, znalazłem przyzwoite obejście, aby sprawdzić, czy kontener zaczął używać docker inspect.

docker inspectzwraca obiekt JSON z dużą ilością informacji o kontenerze, w szczególności o tym, czy kontener jest aktualnie uruchomiony, czy nie. -fFlaga pozwala łatwo wyodrębnić bity potrzebne:

docker inspect -f {{.State.Running}} $CONTAINER_ID

lub

docker inspect -f "{{.State.Running}}" $CONTAINER_ID

zwróci truelub false.

Zauważ, że prawdopodobnie chcesz sleep 1(lub więcej) między uruchomieniem kontenera a sprawdzeniem, czy jest uruchomiony. Jeśli coś jest nie tak z twoją konfiguracją, możliwe, że przez bardzo krótki czas wydawałoby się, że działa ona, zanim faktycznie zakończy działanie.

Jules Olléon
źródło
11
Dlaczego nie użyć docker inspect -f {{.State.Running}} <container-id>i jqzamiast tego użyć ? Po prostu się zastanawiam.
Dharmit,
2
Ponieważ nie zdawałem sobie sprawy, że inspekcja pozwala zrobić to bezpośrednio! Dzięki @DharmitShah to świetna sugestia, zaktualizuję moją odpowiedź.
Jules Olléon
2
Aby pominąć komunikat o błędzie, jeśli nie ma takiego kontenera, przekieruj stderr z 2> /dev/null.
thSoft
Jeśli przypisuję to do zmiennej, pojawia się błąd podczas używania, 2> /dev/nullponieważ nie daje to niczego. Jak mogę ustawić go jako domyślny, falsejeśli kontener nie istnieje?
Jake Sankey
1
Nie dotyczy to jednak kontenerów, które są stale uruchamiane ponownie z powodu zasad ponownego uruchamiania ... To znaczy, jeśli kontener ma ustawioną zasadę ponownego uruchamiania o wartości chyba, że ​​zatrzymano / zawsze, .State.Running zawsze zwróci wartość true ... być zmęczonym!
geekscrap
22

Aby uniknąć parsowania czegokolwiek, możesz użyć docker top , który zwraca 1, jeśli kontener nie jest uruchomiony:

id=$(docker run mycontainer)
if ! docker top $id &>/dev/null
then
    echo "Container crashed unexpectedly..."
    return 1
fi
pedroapero
źródło
10

Przydałoby się docker exec $id true 2>/dev/null || echo not running.

To polecenie nie zapisuje na stdout, jak robi to „docker top”. Zapisuje na stderr, gdy kontener nie jest uruchomiony, ten sam komunikat co „docker top”.

simohe
źródło
2

Zastosowanie powyższych sugestii do scenariusza.

1 - Utwórz skrypt keepMyDockerUp.sh :

vi keepMyDockerUp.sh


#!/bin/bash
Container_ID=INSERT_YOUR_CONTAINER_ID HERE
result=$( docker inspect -f {{.State.Running}} $Container_ID)
echo "result is" $result
if [ $result = "true" ]
then
echo "docker is already running"
else
systemctl restart docker
docker start $Container_ID
fi

2 - Następnie po prostu dodaj go do crona, aby twój skrypt sprawdzał od czasu do czasu, czy twój kontener Docker jest aktywny:

crontab -e

Przejdź do ostatniej linii i dodaj plik skryptu. Na przykład:

* * * * * /root/keepMyDockerUp.sh

3 - Zapisz plik crontab i nigdy nie martw się, że kontener Docker znowu się zepsuje.

Mam nadzieję, że to pomoże...

;-)

Izrael
źródło
1

Musiałem użyć:

$ docker inspect -f {{.State.Health.Status}} xxx

(kontener był w stanie uruchomionym, ale usługa wewnątrz kontenera nie została w pełni uruchomiona.

Część wyników kontroli:

"State": {
    "Status": "running",
    "Running": true,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 1618,
    "ExitCode": 0,
    "Error": "",
    "StartedAt": "2019-03-08T10:39:24.061732398Z",
    "FinishedAt": "0001-01-01T00:00:00Z",
    "Health": {
        "Status": "starting",
        "FailingStreak": 0,
        "Log": []
lvthillo
źródło
Nie wskazywałoby to, czy przebieg się powiódł. Ponieważ kontener może działać, a następnie zawieść.
Vino