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


22

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

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

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

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

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

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

Ответы:


15
  • 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», если служба не запущена. Благодаря @Джунейт, вот обновленный ответ.

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
Если вы используете политику перезапуска, вам также необходимо отфильтровать ее, чтобы она включала только запущенные контейнеры (а не те, которые находятся в состоянии перезапуска):docker ps -q -f "status=running" --no-trunc | grep $(docker-compose ps -q <service_name>)
— Макс.

1
Это работает, но выдает предупреждение «использование grep», если служба не запущена, другими словами, когда grep ....часть заканчивается пустой строкой.
— Джунейт

@ Джунейт Я знаю, да, ты прав. Мысли о том, чтобы избежать / обработать это предупреждение grep?
— Элькимиста

1
@elquimista Да, я решил его с помощью оператора OR: if [ -z `docker-compose ps -q mysql` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q mysql)` ]; then. Это делает следующее: сначала проверяется, существует ли служба вообще (даже если она остановлена), а вторая часть проверяет, действительно ли запущена существующая служба. Возможно, вы захотите включить это в свой пример для будущих читателей, которые смотрят только на принятый ответ. Я думаю, что это полезно.
— Джунейт

12

Что касается версии 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

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


5

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

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

Да, это тоже работает. Помечено как ответ.
— Иван Колмычек

12
Это не говорит вам, работает контейнер или нет, просто существует он или нет. Попробуйте сделать docker-compose upтогда Ctrl-C. docker-compose psЗатем следует показать, что состояния контейнера не «вверх», но docker-compose ps -q service-nameвсе равно дает вам идентификатор.
— Джандерсон

2

У меня была похожая потребность. Тем не менее, у меня есть 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)

0

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

  • Контейнеры либо запускаются и работают бесконечно, либо сразу останавливаются с кодом ошибки (т. е. при отсутствии конфигурации)
  • вы делаете проверку только один раз после того, как 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скрипты, выход с кодом ошибки в случае необходимости переменная окр отсутствует.

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


0

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.