Sprawdź, czy kontener / usługa działa z dokerem-komponuj

22

Używam docker-compose.

Niektóre polecenia podoba up -d service_namelub start service_namewracają od razu i to dość przydatne, jeśli nie chcesz pojemniki uruchomione zależy od stanu powłoki, jak robią z regularnym up service_name. Jedynym przypadkiem użycia jest uruchomienie go z pewnego rodzaju serwera ciągłej integracji / dostarczania.

Ale ten sposób uruchamiania / uruchamiania usług nie zapewnia żadnej informacji zwrotnej na temat faktycznego stanu usługi później.

Odniesienia Docker Compose CLI dla upkomendy wspomina odpowiednią opcję, ale, jak dla wersji 1.7.1, to wzajemnie wykluczające się z -d:

--abort-on-container-exit  Stops all containers if any container was stopped.
                           *Incompatible with -d.*

Czy mogę w jakiś sposób ręcznie sprawdzić, czy kontener rzeczywiście działa i czy nie zatrzymał się z powodu błędu?

Ivan Kolmychek
źródło

Odpowiedzi:

15
  • docker-compose ps -q <service_name> wyświetli identyfikator kontenera bez względu na to, czy jest uruchomiony, czy nie, o ile został utworzony.
  • docker ps pokazuje tylko te, które faktycznie działają.

Połączmy te dwa polecenia:

if [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q <service_name>)` ]; then
  echo "No, it's not running."
else
  echo "Yes, it's running."
fi

docker psdomyślnie wyświetla krótką wersję identyfikatorów, dlatego musimy określić --no-truncflagę.

AKTUALIZACJA : Rzuciło ostrzeżenie „grep use”, jeśli usługa nie była uruchomiona. Dzięki @Dzhuneyt, oto zaktualizowana odpowiedź.

if [ -z `docker-compose ps -q <service_name>` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q <service_name>)` ]; then
  echo "No, it's not running."
else
  echo "Yes, it's running."
fi
elquimista
źródło
Fajny, a także rozwiązuje problem z bieżącą odpowiedzią podaną w komentarzach. Oznaczając to jako nową odpowiedź.
Ivan Kolmychek
1
Jeśli używasz zasady ponownego uruchamiania, musisz ją również przefiltrować, aby uwzględnić tylko działające kontenery (a nie te w stanie ponownego uruchomienia):docker ps -q -f "status=running" --no-trunc | grep $(docker-compose ps -q <service_name>)
Maks.
1
Działa to, ale wyświetla ostrzeżenie „użycie grep”, jeśli usługa nie jest uruchomiona, innymi słowy, gdy grep ....część kończy się pustym ciągiem.
Dzhuneyt,
@Dzhuneyt Wiem, tak, masz rację. Myśli, aby uniknąć / poradzić sobie z ostrzeżeniem grep?
elquimista
1
@elquimista Tak, rozwiązać go za pomocą operatora OR: if [ -z `docker-compose ps -q mysql` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q mysql)` ]; then. To robi: najpierw sprawdza, czy usługa w ogóle istnieje (nawet jeśli jest zatrzymana), a druga część sprawdza, czy istniejąca usługa faktycznie działa. Możesz dołączyć to do swojego przykładu dla przyszłych czytelników, którzy przeglądają tylko zaakceptowaną odpowiedź. Myślę, że to jest przydatne.
Dzhuneyt
12

Jeśli chodzi o wersję 1.7.1, nie ma takich poleceń wbudowanych.

Zamiast tego execmożna użyć w podobny sposób.

Po uruchomieniu go dla usługi, która ma kilka kontenerów, będzie działał poprawnie:

~/apperture-science $ docker-compose exec chell echo 'Still alive!'
Still alive!
~/apperture-science $ echo $?
0

Ale gdy uruchomisz go dla usługi, która nie ma uruchomionych kontenerów usług , wyświetli błąd:

~/apperture-science $ docker-compose exec glados echo "Still alive!"
ERROR: No container found for apperture-science-glados_1
~/apperture-science $ echo $?
1

Można go więc wykorzystać do sprawdzenia, czy istnieją jakieś „żywe” pojemniki dla danej usługi.

Ivan Kolmychek
źródło
5

Możesz uruchomić:

docker-compose ps -q service-name

Otrzymasz identyfikator kontenera, jeśli service-namejest uruchomiony. Coś jak:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

Jeśli usługa nie działa, dane wyjściowe są puste, więc jeśli chcesz użyć tego w skrypcie, możesz zrobić coś takiego:

IS_RUNNING=`docker-compose ps -q service-name`
if [[ "$IS_RUNNING" != "" ]]; then
    echo "The service is running!!!"
fi
alejandropg
źródło
Tak, to też działa. Oznaczono to jako odpowiedź teraz.
Ivan Kolmychek
12
Nie mówi to, czy kontener jest uruchomiony, czy nie, tylko czy istnieje, czy nie. Spróbuj zrobić docker-compose upCtrl-C. docker-compose pspowinien wtedy pokazać, że stany kontenera nie są „w górę”, ale docker-compose ps -q service-namenadal dają ci identyfikator.
djanderson
2

Miałem podobną potrzebę. Mam jednak restart: alwaysw swoim środowisku. Może być więc trochę trudne wykrycie, czy coś się zawiesza i restartuje w pętli.

Zrobiłem kontrolę Icinga / Nagios, aby również porównać czasy utworzenia i rozpoczęcia. Może przyda się komuś innemu:

#!/usr/bin/env python
from __future__ import print_function
import argparse
from datetime import timedelta
from datetime import datetime
import sys

from dateutil.parser import parse as parse_date
import docker
import pytz
parser = argparse.ArgumentParser()
parser.add_argument("compose_project",
                    help="The name of the docker-compose project")
parser.add_argument("compose_service",
                    help="The name of the docker-compose service")
args = vars(parser.parse_args())

client = docker.from_env()
service_containers = client.containers.list(filters={
    "label": [
        "com.docker.compose.oneoff=False",
        "com.docker.compose.project={}".format(args["compose_project"]),
        "com.docker.compose.service={}".format(args["compose_service"])
    ]})

if len(service_containers) == 0:
    print("CRITICAL: project({})/service({}) doesn't exist!".format(
        args["compose_project"], args["compose_service"]))
    sys.exit(2)
elif len(service_containers) > 1:
    print("CRITICAL: project({})/service({}) has more than 1 "
          "container!".format(
              args["compose_project"], args["compose_service"]))
    sys.exit(2)

service_container = service_containers[0]
created_at = parse_date(service_container.attrs['Created'])
status = service_container.attrs['State']['Status']
started_at = parse_date(service_container.attrs['State']['StartedAt'])
now = datetime.utcnow().replace(tzinfo=pytz.utc)
uptime = now - started_at

if status in ['stopped', 'exited', 'dead']:
    print("CRITICAL: project({})/service({}) is status={}".format(
        args["compose_project"], args["compose_service"], status))
    sys.exit(2)

if (started_at - created_at) > timedelta(minutes=5):
    if uptime < timedelta(seconds=5):
        print("CRITICAL: project({})/service({}) appears to be "
              "crash-looping".format(
                  args["compose_project"], args["compose_service"]))
        sys.exit(2)

if status == "restarting":
    print("WARNING: project({})/service({}) is restarting".format(
        args["compose_project"], args["compose_service"]))
    sys.exit(1)

print ("OK: project({})/service({}) is up for {}".format(
    args["compose_project"], args["compose_service"], uptime
))
sys.exit(0)
jof
źródło
0

Jeśli przyjmiesz ten scenariusz:

  • kontenery albo uruchamiają się i działają w nieskończoność, albo zatrzymują się natychmiast z kodem błędu (tj. z powodu braku konfiguracji)
  • robisz to tylko raz po powrocie dokera-komponuj up -d

można sprawdzić, czy nie ma żadnego pojemnika zatrzymane z powodu błędu z: docker ps -a | grep 'Exited (255)'.

Ta kontrola działa poprawnie nawet w przypadku kontenerów, które mają się natychmiast zatrzymać bez błędu (tj. Pojemniki danych), ponieważ ich status (od docker ps -a) jest oznaczony jako Exited (0).

Na przykład w naszym docker-compose.yml zaczynamy nasze kontenery od:

command: sh -c 'node dotenv_check.js && pm2 start --no-daemon src/worker.js --watch'

Do php-fpm używamy podobnego polecenia:

command: >-
  sh -c '
  set -e;
  for PROJECT in frontend backend; do
    cd /var/www/$${PROJECT};
    php dotenv_check.php;
  done;
  php-fpm
  '

dotenv_check.jsI dotenv_check.phpsą skrypty, które wyjście z kodem błędu w przypadku, gdy wymagana zmienna ENV brakuje.

set -ePolecenia informuje skrypt do zatrzymania w przypadku błędu, który, z kolei, będą natychmiast zatrzymać pojemnik. Informacje o set-e

Fabio
źródło
0

Co powiesz na to?

docker-compose ps | awk '$4 == "Up" {print $1}' | grep <service-name>

wyświetlasz listę procesów, wybierasz wiersze, w których „kolumna” znajduje się w kolumnie 4, i filtrujesz w celu znalezienia dopasowania w nazwie usługi.

George Mauer
źródło