Назад | Перейти на главную страницу

Проверьте, запущен ли контейнер / служба с помощью docker-compose

Я использую docker-compose.

Некоторые команды вроде up -d service_name или start service_name возвращаются сразу, и это очень полезно, если вы не хотите, чтобы работающие контейнеры зависели от состояния оболочки, как это происходит с обычным up service_name. Единственный вариант использования - запускать его с какого-то сервера непрерывной интеграции / доставки.

Но этот способ запуска / запуска служб не дает никакой обратной связи о фактическом состоянии службы впоследствии.

В Справочник по интерфейсу командной строки Docker Compose для up команда упоминает соответствующий вариант, но, что касается версии 1.7.1, он является взаимоисключающим с -d:

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

Могу ли я как-то вручную проверить, действительно ли контейнер работает и не остановился из-за ошибки?

  • docker-compose ps -q <service_name> будет отображать идентификатор контейнера независимо от того, запущен он или нет, пока он был создан.
  • docker ps показывает только те, которые действительно работают.

Объединим эти две команды:

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 по умолчанию показывает сокращенную версию идентификаторов, поэтому нам нужно указать --no-trunc флаг.

ОБНОВИТЬ: Он выдавал предупреждение об использовании grep, если служба не работала. Благодаря @Dzhuneyt, вот обновленный ответ.

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

Что касается версии 1.7.1, таких встроенных команд нет.

Вместо этого exec можно использовать аналогичным образом.

Когда вы запустите его для службы, в которой есть несколько контейнеров, она будет работать нормально:

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

Но когда вы запускаете его для службы, которая не запущена служба контейнеры, он покажет ошибку:

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

Таким образом, с его помощью можно проверить, есть ли «живые» контейнеры для данной службы.

Вы можете запустить:

docker-compose ps -q service-name

И вы получите идентификатор контейнера, если service-name это работает. Что-то вроде:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

Если служба не запущена, вывод будет пустым, поэтому, если вы хотите использовать это в сценарии, вы можете сделать что-то вроде:

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

У меня была аналогичная потребность. Однако у меня есть restart: always в моем окружении. Таким образом, может быть немного сложно определить, что что-то выходит из строя и перезапускается в цикле.

Я сделал проверку Icinga / Nagios, чтобы также сравнить время создания и время запуска. Может быть, это пригодится кому-то еще в будущем:

#!/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)

Увидеть все запущенные службы:

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

Увидеть, если ваша служба это работает:

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

Обратите внимание, что --filter должен использоваться с --services по какой-то иностранной причине.

Если вы предполагаете этот сценарий:

  • контейнеры либо запускаются и работают на неопределенный срок, либо немедленно останавливаются с кодом ошибки (например, из-за отсутствия конфигурации)
  • вы выполняете проверку только один раз после возврата docker-compose up -d

вы можете проверить, есть ли остановленный контейнер из-за ошибки: docker ps -a | grep 'Exited (255)'.

Эта проверка работает правильно даже в случае контейнеров, которые, как ожидается, немедленно остановятся без ошибок (например, контейнеры данных), поскольку их статус (от docker ps -a) отмечен как Exited (0).

Например, в нашем docker-compose.yml мы запускаем наши контейнеры с:

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

Для php-fpm мы используем аналогичную команду:

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

В dotenv_check.js и dotenv_check.php это скрипты, которые выходят с кодом ошибки в случае отсутствия необходимой переменной env.

В set -e команда, сообщает скрипту останавливаться при ошибке, которая, в свою очередь, немедленно останавливает контейнер. О set-e

Как насчет этого?

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

вы перечисляете процессы, выбираете строки, где «Вверх» находится в столбце 4, и выполняете фильтрацию на соответствие имени службы.