Как выполнить команду Bash, только если Docker-контейнер с данным именем не существует?

На компьютере Jenkins я хотел бы создать докер-контейнер с указанным именем, только если он еще не существует (в сценарии оболочки). Я думал, что мог бы запустить команду для создания контейнера независимо и игнорировать сбой, если он был, но это приводит к сбою моей работы jenkins.

Следовательно, я хотел бы знать, как я могу проверить, существует ли док-контейнер или нет с помощью bash.

Ответы на вопрос(8)

Ты можешь использоватьfilter а такжеformat варианты дляdocker ps команда, чтобы избежать труб с Unix-утилиты, такие какgrep, awk и т.п.

name='nginx'

[[ $(docker ps --filter "name=^/$name$" --format '{{.Names}}') == $name ]] ||
docker run -d --name mynginx <nginx-image>
 Henning11 мар. 2018 г., 17:35
действительно здорово и просто! Спасибо!
 anubhava31 июл. 2018 г., 15:01
Спасибо @bcoughlan за очень полезный совет.
 Ciro Santilli 新疆改造中心996ICU六四事件28 авг. 2018 г., 09:39
@bcoughlan, где это задокументировано? анубхав:stackoverflow.com/a/43202632/895245 уже упоминал об этом ранее, вы хотели бы к этому.
 bcoughlan31 июл. 2018 г., 12:57
Это будет соответствовать частичной строке, но вы можете получить точное совпадение с--filter "name=^/$name$"
Это не будет работать или будет очень резким, если имя контейнера является подстрокой имени другого контейнера, так как-f фильтры для подстрок, не полное совпадение, я бы предпочел просто grep это:stackoverflow.com/a/50841982/895245
 bcoughlan28 авг. 2018 г., 10:16
@CiroSantilli seem 改造 中心 六四 事件 seem Кажется, это не задокументировано в документации докера ps. Строка интерпретируется Docker как регулярное выражение, в имени есть символ '/', хотя я не уверен, если / почему первый$ нужно.

Я полагаю

docker container inspect <container-name> || docker run...

Так как Docker контейнер проверяет вызов установит $? в 1, если контейнер не существует (не может проверить), но в 0, если он существует (это касается остановленных контейнеров). Поэтому команда run будет вызываться только в том случае, если контейнер не существует должным образом.

 Mikhail Vasin24 февр. 2018 г., 12:13
Я бы даже пошел сdocker container inspect <container-name> > /dev/null 2>&1 отменить как успешный, так и неудачный вывод.

Надежный grep^$ без недокументированного поведения

Это самый точный и гибкий подход, который я мог найти:

container_name=mycont
if sudo docker ps -a --format '{{.Names}}' | grep -Eq "^${container_name}\$"; then
  echo exists
else
  echo 'does not exist'
fi

Обоснование:

https://stackoverflow.com/a/38576401/895245 не работает, если имя контейнера является подстрокой в ​​другом контейнереhttps://stackoverflow.com/a/45171589/895245 а такжеhttps://stackoverflow.com/a/43202632/895245 полагаться на поведение, для которого я не мог найти документацию: состояние выходаdocker container inspect и это-f name принимает регулярные выражения некоторого вида.

питон

Версия Python для удобства, так как я в конечном итоге использовал ее в проекте:

containers = subprocess.check_output([
        'sudo',
        'docker',
        'ps',
        '-a',
        '--format', '{{.Names}}',
]).decode()
if container_name in containers.split():
    # Exists.

Еще короче сверх докера:

docker top <name> || docker run --name <name> <image>

docker top возвращает ненулевое значение, когда нет контейнеров, соответствующих имени, запущенному, в противном случае возвращает pid, пользователя, время выполнения и команду.

Я использую следующий код, чтобы определить, существует ли контейнер Docker:

CONTAINER_NAME='my_docker_container'
# Checking if docker container with $CONTAINER_NAME name exists.
COUNT=$(docker ps -a | grep "$CONTAINER_NAME" | wc -l)
if (($COUNT > 0)); then
    echo 'container exists'
fi
Сбой для совпадения подстроки, или если другие поляps -a совпадать, и вам не нужноwcСтатус grep можно использовать напрямую. Моя версия не страдает от этих проблем:stackoverflow.com/a/50841982/895245
if [[ $(sudo docker inspect --format . <container-name>) == "." ]]; then
  docker run <container-name>;
fi

объяснение:

Уже есть подобный ответ. Разница здесь в том,--format . вариант (вы также можете использовать-f .). Это удаляет все детали из команды проверки. Докер используетперейти шаблонный формат, что в данном случае означает, что он будет копировать на выход все, что не распознает.

Так-f itIsThere вернусьitIsThere если контейнер с этим namex выходит. Если этого не произойдет, Docker вернет код ошибки и сообщение (Error: No such object: <container-name>).

Я нашел это в журналах Дженкинс.

Просто префикс имени с ^ / и суффикс $. Кажется, это регулярное выражение:

CONTAINER_NAME='mycontainername'

CID=$(docker ps -q -f status=running -f name=^/${CONTAINER_NAME}$)
if [ ! "${CID}" ]; then
  echo "Container doesn't exist"
fi
unset CID
Документация / цитата из источника была бы хорошей.
Решение Вопроса

Вы можете проверить наличие несуществующего контейнера с помощью поиска<name> и запустите его позже так:

[ ! "$(docker ps -a | grep <name>)" ] && docker run -d --name <name> <image>

Лучше:

Использоватьhttps://docs.docker.com/engine/reference/commandline/ps/ и проверьте, блокируется ли вышедший контейнер, так что вы можете сначала удалить его перед запуском контейнера:

if [ ! "$(docker ps -q -f name=<name>)" ]; then
    if [ "$(docker ps -aq -f status=exited -f name=<name>)" ]; then
        # cleanup
        docker rm <name>
    fi
    # run your container
    docker run -d --name <name> my-docker-image
fi
 Alexander Mills30 апр. 2019 г., 02:10
Кажется, что эти команды всегда выходят с 0 (ноль)
 ldg26 июл. 2016 г., 04:03
Правильно - вам нужно-a или попытка запустить вышедший контейнер не удастся.
 David16 апр. 2017 г., 04:27
синтаксическая ошибка, должна быть: [! "$ (docker ps | grep <name>)"] && docker run -d --name <name> <image>
 Daniel Farrell14 нояб. 2017 г., 22:20
Ответ WiRai короче и не имеет проблем, связанных с grep
 ferdy22 мар. 2017 г., 09:28
@MaximTkach Вот почему лучше использовать второй подход, когда вы полностью определяете имя контейнера в командах docker ps. Но вы также можете ввести регулярное выражение в команду grep для поиска пробелов до и после имени. Этот тест намеренно оставлен читателю.
 Ciro Santilli 新疆改造中心996ICU六四事件13 июн. 2018 г., 18:22
@MaximTkach решено в:stackoverflow.com/a/50841982/895245
 Limited Atonement17 июл. 2018 г., 22:31
Как примечание,docker ps это псевдоним дляdocker container ls.
 Maxim Tkach13 мар. 2017 г., 16:22
Этот ответ не работает, если у вас есть два контейнера с похожим именем. Например: cool.project (контейнер 1) и dashboard.cool.project (контейнер 2)

Ваш ответ на вопрос