Как определить, удалось ли запустить докер программно?

83

Я пишу очень простой сценарий bash, чтобы быстро проверить, что мой контейнер по-прежнему строится и запускается правильно и что приложение внутри отвечает на запросы.

Иногда происходит docker runсбой, например, потому что порт, к которому я пытаюсь привязать контейнер, уже выделен. Но когда это происходит docker run, код выхода по-прежнему равен 0, поэтому я не могу использовать код выхода. Как я могу программно проверить правильность запуска контейнера?

Я рассматриваю следующие решения:

  • проанализировать вывод на наличие ошибок
  • docker ps чтобы увидеть, запущен ли контейнер

но они оба кажутся немного излишними и уродливыми. Мне не хватает лучшего способа проверить, docker runудалось ли ?

Жюль Оллеон
источник
1
Я не уверен, в чем проблема. Если рассматриваемый процесс ведет себя обычным образом, вы можете просто проверить код выхода. Если он выдает код выхода 0 даже для неудачных случаев, попробуйте выяснить, является ли это ошибкой. Если программа в любом случае возвращает код выхода 0, то вам, вероятно, не остается другого выбора, кроме как проанализировать вывод.
devnull
Как сказал @devnull, если вы не можете доверять, что docker runвернет ненулевой код возврата в случае неудачи, как вы указываете, тогда все, что вы можете сделать, это проанализировать вывод (который может быть сложным или хрупким) или использовать другую команду (т.е. ваше psпредложение ), чтобы проверить результат первой команды. Возможно, вы захотите подать заявку в Docker, чтобы узнать, могут ли они также исправить код возврата run.
Etan Reisner
Убедитесь, что у вас последняя версия.
ooga
В вашем контейнере запускается собственный код? если это так, вы можете экспортировать порт в свой Dockerfile, когда ваша программа находится в стабильном рабочем состоянии, отправьте на этот порт сообщение «OK». Ваш клиентский код ожидает сообщения «ОК».
rexposadas
3
Можете ли вы привести пример того, как вы запускаете докер и какую версию? Быстрый тест показывает, что код выхода из докера для меня равен 1docker run -d -p 9010:9010 busybox true ; echo $?
Абель Муньо

Ответы:

118

Как предложил Абель Муйно в комментариях, это могло быть исправлено в более поздних версиях Docker (сейчас я использую 0.9.1).

Но если вы, как и я, временно застряли в более старой версии, я нашел достойный обходной путь, чтобы проверить, запускался ли контейнер с помощью docker inspect.

docker inspectвозвращает объект JSON с большим количеством информации о контейнере и, в частности, о том, запущен ли контейнер в данный момент или нет. -fФлаг позволяет легко извлекать биты , необходимые:

docker inspect -f {{.State.Running}} $CONTAINER_ID

или же

docker inspect -f "{{.State.Running}}" $CONTAINER_ID

вернется trueили false.

Обратите внимание, что вы, вероятно, захотите sleep 1(или больше) между запуском контейнера и проверкой, работает ли он. Если что-то не так с вашей настройкой, возможно, она будет отображаться как «запущенная» в течение очень короткого времени, прежде чем фактически завершится.

Жюль Оллеон
источник
11
Почему бы не docker inspect -f {{.State.Running}} <container-id>использовать jqвместо этого? Просто интересуюсь.
Дхармит 07
2
Потому что я не понимал, что inspect позволяет делать это напрямую! Спасибо @DharmitShah, это отличное предложение, я обновлю свой ответ.
Жюль Оллеон 07
2
Чтобы подавить сообщение об ошибке, если такого контейнера нет, перенаправьте stderr с помощью 2> /dev/null.
thSoft
Если я назначаю это переменной, я получаю сообщение об ошибке при использовании, 2> /dev/nullпоскольку она ничего не оценивает. Как я могу сделать это по умолчанию, falseесли контейнер не существует?
Джейк Сэнки,
1
Однако это не вмещает контейнеры, которые постоянно перезапускаются из-за политики перезапуска ... То есть, если для контейнера задана политика перезапуска без остановки / всегда, .State.Running всегда будет возвращать истину .... Просто что-то для надоедать!
geekscrap
22

Чтобы ничего не анализировать, вы можете использовать docker top , который возвращает 1, если контейнер не запущен:

id=$(docker run mycontainer)
if ! docker top $id &>/dev/null
then
    echo "Container crashed unexpectedly..."
    return 1
fi
педроаперо
источник
10

Мы могли бы использовать docker exec $id true 2>/dev/null || echo not running .

Эта команда не записывает в stdout, как docker top. Он пишет в stderr, когда контейнер не запущен, то же сообщение, что и «docker top».

симохе
источник
2

Применение вышеупомянутых предложений к сценарию.

1 - Создайте скрипт keepMyDockerUp.sh :

vi keepMyDockerUp.sh


#!/bin/bash
Container_ID=INSERT_YOUR_CONTAINER_ID HERE
result=$( docker inspect -f {{.State.Running}} $Container_ID)
echo "result is" $result
if [ $result = "true" ]
then
echo "docker is already running"
else
systemctl restart docker
docker start $Container_ID
fi

2 - Затем просто добавьте его в cron, чтобы ваш скрипт время от времени проверял, включен ли ваш контейнер Docker:

crontab -e

Перейдите к последней строке и добавьте файл сценария. Например:

* * * * * /root/keepMyDockerUp.sh

3 - Сохраните crontab и никогда не беспокойтесь о том, что ваш контейнер Docker снова упадет.

Надеюсь, поможет...

;-)

Израиль
источник
1

Пришлось использовать:

$ docker inspect -f {{.State.Health.Status}} xxx

(контейнер был в состоянии запущен, но служба внутри контейнера не была полностью запущена.

Часть вывода проверки:

"State": {
    "Status": "running",
    "Running": true,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 1618,
    "ExitCode": 0,
    "Error": "",
    "StartedAt": "2019-03-08T10:39:24.061732398Z",
    "FinishedAt": "0001-01-01T00:00:00Z",
    "Health": {
        "Status": "starting",
        "FailingStreak": 0,
        "Log": []
lvthillo
источник
Это не будет утверждать, что запуск был успешным. Потому что контейнер может запуститься, а затем выйти из строя.
Vino