O cheque é contêiner / serviço em execução com docker-compose

22

Eu estou usando o docker-compose.

Alguns comandos gostam up -d service_nameou start service_nameestão retornando imediatamente e isso é bastante útil se você não quiser que os contêineres em execução dependam do estado do shell, como fazem com o regular up service_name. O único caso de uso está sendo executado em algum tipo de servidor de integração / entrega contínuo.

Mas essa maneira de executar / iniciar serviços não fornece nenhum feedback sobre o estado real do serviço posteriormente.

A referência da CLI do Docker Compose para o upcomando menciona a opção relevante, mas, como para a versão 1.7.1, é mutuamente exclusiva com -d:

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

De alguma forma, posso verificar manualmente se o contêiner está realmente funcionando e não parou por causa de algum erro?

Ivan Kolmychek
fonte

Respostas:

15
  • docker-compose ps -q <service_name> exibirá o ID do contêiner, independentemente de estar em execução ou não, desde que tenha sido criado.
  • docker ps mostra apenas aqueles que estão realmente em execução.

Vamos combinar estes dois 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 psmostra a versão curta dos IDs por padrão, portanto, precisamos especificar o --no-truncsinalizador.

ATUALIZAÇÃO : emitiu um aviso de "uso de grep" se o serviço não estava sendo executado. Graças a @Dzhuneyt, aqui está a resposta atualizada.

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
fonte
Nice, e também aborda o problema com a resposta atual que foi declarada nos comentários. Marcando isso como uma nova resposta.
Ivan Kolmychek
11
Se você estiver usando uma política de reinício você também precisa filtrá-la para incluir apenas correndo recipientes (em vez de os em um estado de reiniciar):docker ps -q -f "status=running" --no-trunc | grep $(docker-compose ps -q <service_name>)
Max
11
Isso funciona, mas lança um aviso de "uso de grep" se o serviço não estiver sendo executado, ou seja, quando a grep ....peça terminar com uma string vazia.
Dzhuneyt 12/07
@Dzhuneyt Eu sei, sim, você está certo. Pensamentos para evitar / lidar com esse aviso grep?
elquimista 12/07
11
@elquimista Sim, eu resolvi-lo usando o operador OR: if [ -z `docker-compose ps -q mysql` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q mysql)` ]; then. O que isso faz é: primeiro verifica se o serviço existe (mesmo se estiver parado) e a segunda parte verifica se o serviço existente está realmente em execução. Você pode incluir isso no seu exemplo para futuros leitores que examinam apenas a resposta aceita. Eu acho que é útil.
Dzhuneyt 15/07
12

Quanto à versão 1.7.1, não existem comandos desse tipo embutidos.

Em vez disso, o execpode ser usado de maneira semelhante.

Quando você o executa para o serviço que possui alguns contêineres, ele funcionará ok:

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

Mas quando você executá-lo para o serviço, que não tem em execução de serviços de contentores, ele irá mostrar um erro:

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

Portanto, ele pode ser usado para verificar se existem contêineres "vivos" para um determinado serviço.

Ivan Kolmychek
fonte
5

Você pode correr:

docker-compose ps -q service-name

E você receberá o ID do contêiner, se service-nameestiver em execução. Algo como:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

Se o serviço não estiver sendo executado, a saída estará vazia; portanto, se você quiser usá-lo em um script, poderá fazer algo como:

IS_RUNNING=`docker-compose ps -q service-name`
if [[ "$IS_RUNNING" != "" ]]; then
    echo "The service is running!!!"
fi
alejandropg
fonte
Sim, isso também funciona. Marcado como resposta agora.
Ivan Kolmychek
12
Isso não informa se o contêiner está em execução ou não, apenas se existe ou não. Tente fazer docker-compose upCtrl-C. docker-compose psdeve mostrar que os estados do contêiner não estão "Ativos", mas docker-compose ps -q service-nameainda fornecem um ID.
22618 djanderson
2

Eu tive uma necessidade semelhante. No entanto, eu tenho um restart: alwaysno meu ambiente. Portanto, pode ser um pouco complicado detectar se algo está travando e reiniciando em um loop.

Fiz uma verificação Icinga / Nagios para comparar também os horários de criação e início. Talvez seja útil para alguém na mesma linha:

#!/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
fonte
0

Se você assumir este cenário:

  • os contêineres iniciam e executam indefinidamente ou param imediatamente com um código de erro (por exemplo, na falta de configuração)
  • você faz a verificação apenas uma vez após o retorno do docker-compose up -d

você pode verificar se há qualquer recipiente parou devido a um erro com: docker ps -a | grep 'Exited (255)'.

Essa verificação funciona corretamente, mesmo no caso de contêineres que devem parar imediatamente sem erro (ou seja, contêineres de dados), pois seu status (de docker ps -a) é marcado como Exited (0).

Por exemplo, em nosso docker-compose.yml, iniciamos nossos contêineres com:

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

Para php-fpm, usamos um comando semelhante:

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

Os scripts dotenv_check.jse dotenv_check.phpsão encerrados com um código de erro, caso uma variável env necessária esteja ausente.

O set -ecomando diz ao script para parar por erro, o que, por sua vez, interrompe imediatamente o contêiner. Sobre set-e

Fabio
fonte
0

Que tal agora?

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

você lista os processos, selecione as linhas em que "Para cima" está na coluna 4 e filtra para obter uma correspondência no nome do serviço.

George Mauer
fonte