Compruebe si el contenedor/servicio se está ejecutando con docker-compose

Estoy usando el docker-compose.

Algunos comandos como up -d service_name o start service_name están regresando de inmediato y esto es bastante útil si no desea que los contenedores que se ejecutan dependan del estado del shell, como lo hacen con regular up service_name. El único caso de uso es ejecutarlo desde algún tipo de servidor de integración/entrega continuo.

Pero esta forma de ejecutar / iniciar servicios no proporciona ninguna retroalimentación sobre el estado real del servicio después.

El Referencia de la CLI de Docker Compose para up comando menciona la opción relevante, pero, en cuanto a la versión 1.7.1, es mutuamente excluyente con -d:

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

¿Puedo de alguna manera verificar manualmente que el contenedor realmente funciona y no se ha detenido debido a algún error?

  • docker-compose ps -q <service_name> mostrará el ID del contenedor sin importar si se está ejecutando o no, siempre que se haya creado.
  • docker ps muestra solo aquellos que realmente se están ejecutando.

Combinemos estos dos comandos:

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 ps muestra la versión corta de los ID de forma predeterminada, por lo que debemos especificar --no-trunc bandera.

ACTUALIZAR: Lanzaba una advertencia de "uso de grep" si el servicio no se estaba ejecutando. Gracias a @Dzhuneyt, aquí está la respuesta actualizada.

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

En cuanto a la versión 1.7.1, no hay tales comandos incorporados.

En cambio, el exec se puede usar de manera similar.

Cuando lo ejecute para el servicio que tiene algunos contenedores, se ejecutará bien:

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

Pero cuando lo ejecuta para el servicio que no se está ejecutando Servicio de lo contrario, mostrará un error:

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

Por lo tanto, se puede usar para verificar si hay contenedores "vivos" para un servicio determinado.

Ver todo servicios en ejecución:

docker-compose ps --services --filter "status=running"

Para ver si su servicio se está ejecutando:

docker-compose ps --services --filter "status=running" | grep <your-service>

Tenga en cuenta que --filter debe usarse con --services por alguna extraña razón.

Puedes correr:

docker-compose ps -q service-name

Y obtendrá la identificación del contenedor si service-name está corriendo. Algo así como:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

Si el servicio no se está ejecutando, la salida está vacía, por lo que si desea usar esto en un script, puede hacer algo como:

IS_RUNNING=`docker-compose ps -q service-name`if [[ "$IS_RUNNING" != "" ]]; then    echo "The service is running!!!"fi

Yo tenía una necesidad similar. Sin embargo, tengo un restart: always en mi entorno. Por lo tanto, puede ser un poco complicado detectar si algo se bloquea y se reinicia en un bucle.

Hice una comprobación de Icnga / Nagios para comparar también las horas creadas y de inicio. Tal vez sea útil para alguien más en el futuro:

#!/usr/bin/env pythonfrom __future__ import print_functionimport argparsefrom datetime import timedeltafrom datetime import datetimeimport sysfrom dateutil.parser import parse as parse_dateimport dockerimport pytzparser = 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_atif 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)

Aquí hay uno simple, que devuelve el estado actual del servicio:

docker inspect --format "{{.State.Status}}" $(docker-compose ps -q your_service_name)

Esto devuelve solo el estado del contenedor docker. Si desea verificar el estado real de su aplicación, debe agregar HEALTHCHECK a su Dockerfile (https://docs.docker.com/engine/reference/builder/#healthcheck). Después puede inspeccionarlo con:

docker inspect --format "{{.State.Health.Status}}" $(docker-compose ps -q your_service_name)

¿Qué tal esto?

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

enumera los procesos, selecciona las líneas donde está "Arriba" en la columna 4 y filtra para encontrar una coincidencia en el nombre del servicio.

Si asume este escenario:

  • los contenedores se inician y ejecutan indefinidamente o se detienen inmediatamente con un código de error (es decir, por falta de configuración)
  • realiza la comprobación solo una vez después de que docker-compose up-d regrese

puede comprobar si hay algún contenedor detenido debido a un error con:docker ps -a | grep 'Exited (255)'.

Esta comprobación funciona correctamente incluso en el caso de contenedores que se espera que se detengan inmediatamente sin errores (es decir, contenedores de datos), ya que su estado (de docker ps -a) está marcado como Exited (0).

Por ejemplo, en nuestro docker-compose.yml, comenzamos nuestros contenedores con:

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

Para php-fpm, usamos un comando similar:

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

El dotenv_check.js y dotenv_check.php son scripts que salen con un código de error en caso de que falte una variable env requerida.

El set -e comando, le dice al script que se detenga en caso de error, lo que, a su vez, detendrá inmediatamente el contenedor. Acerca de set-e

Puedes grep para (healthy) o/y (unhealthy) imágenes para actuar correctamente.

En este ejemplo, estoy probando docker-compose cada 5 segundos para ejecutar el servicio con (healthy) estatus.Si el script encuentra tal servicio, interrumpirá la ejecución.Si el script supera los 300 segundos, se cerrará con un código de error.

#!/bin/bashSECONDS=0LIMIT=300x=$(docker-compose -f /mnt/<service>/docker-compose.yaml ps <service> | grep -c '(healthy)')while [[ $x == "0" ]]; do    echo "Please wait until <service> becomes healthy"    sleep 5    x=$(docker-compose -f /mnt/<service>/docker-compose.yaml ps <service> | grep -c '(healthy)')    EXPIRED=$SECONDS    if [[ $x == "1" ]]; then      echo "<service> is healthy..."      break    elif [[ $LIMIT -lt $EXPIRED ]]; then      echo "<service> startup has exceeded 5m timeout, exiting!"      exit 1    fidone

Aquí hay una línea simplificada basada en la respuesta de almquista:

docker ps -q --no-trunc | grep -q "^$(docker-compose ps -q app-service)$"

Usamos grep -q un código de salida distinto de cero indica que el servicio no se está ejecutando. Por ejemplo:

if docker ps -q --no-trunc | grep -q "^$(dc-audo-dev ps -q app-service)$"; then    echo "Container is still running..."fi