仅当不存在具有给定名称的Docker容器时,如何执行Bash命令?


80

在Jenkins机器上,我只想创建一个具有指定名称的docker容器(如果它不存在)(在shell脚本中)。我以为我可能会运行该命令来创建容器,而忽略存在该容器的失败,但这会导致我的詹金斯工作失败。

因此,我想知道如何检查bash是否存在docker容器。

Answers:


150

您可以通过grepping a检查是否存在正在运行的容器,<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

2
正确-您需要-a或尝试运行退出的容器都会失败。
ldg '16

8
如果您有两个名称相似的容器,则此响应不起作用。例如:cool.project(容器1)和dashboard.cool.project(容器2)
Maxim Tkach

1
@MaximTkach这就是为什么使用第二种方法更好的原因,您可以在docker ps命令中完全限定容器的名称。但是,您也可以在grep命令中引入一个正则表达式,以在名称前后查找空白。该测试是有意留给读者的。
弗迪

1
语法错误,应为:[!“ $(docker ps | grep <名称>)”] && docker run -d --name <名称> <图像>
David David

3
WiRai的回答是没有grep的相关问题短,患有
丹尼尔·法雷尔

40

我想

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

因为码头集装箱检查调用将设置$?如果容器不存在(无法检查),则为1;如果容器不存在,则为0(这涉及已停止的容器)。因此,如果容器不按预期存在,则将仅调用run命令。


15
我什docker container inspect <container-name> > /dev/null 2>&1至会舍弃成功和不成功的输出。
米哈伊尔·瓦辛

29

您可以使用filterformat查看选项docker ps命令,以避免管道与UNIX工具一样grepawk等等。

name='nginx'

[[ $(docker ps --filter "name=^/$name$" --format '{{.Names}}') == $name ]] ||
docker run -d --name mynginx <nginx-image>

5
这将在部分字符串上匹配,但是您可以通过--filter "name=^/$name$"
bcoughlan

@bcoughlan记录在哪里?anubhava:stackoverflow.com/a/43202632/895245之前已经提到过,您应该这样做。
西罗Santilli郝海东冠状病六四事件法轮功

2
@CiroSantilli新疆改造中心六四事件法轮功它似乎没有记录在docker ps文档中。Docker将字符串解释为正则表达式,名称中带有'/'字符,尽管我不确定是否/为什么$需要第一个字符。
bcoughlan

13

只需在名称前加上^ /并在其后缀$。看来这是一个正则表达式:

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

13

使用docker top更短:

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

docker top 如果没有与运行名称匹配的容器,则返回非零,否则返回pid,用户,运行时间和命令。


5

强大的grep,^$没有未记录的行为

这是我能找到的最精确,最灵活的方法:

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

理由:

  1. 如果容器名称是另一个容器中的子字符串,则https://stackoverflow.com/a/38576401/895245不起作用
  2. https://stackoverflow.com/a/45171589/895245https://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.

2

我使用以下代码来确定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 status。我的版本没有遇到这些问题:stackoverflow.com/a/50841982/895245
Ciro Santilli郝海东冠状病六四事件法轮功

2

这是我检查容器是否正在运行,停止它,然后将其删除的解决方案。

CNAME=$CONTAINER_NAME-$CODE_VERSION
if [ "$(docker ps -qa -f name=$CNAME)" ]; then
    echo ":: Found container - $CNAME"
    if [ "$(docker ps -q -f name=$CNAME)" ]; then
        echo ":: Stopping running container - $CNAME"
        docker stop $CNAME;
    fi
    echo ":: Removing stopped container - $CNAME"
    docker rm $CNAME;
fi

我已经搜索了太多次了,因为即使上面的100+答案实际上也不起作用。我认为原因是对docker ps的误解。docker ps列出正在运行的容器。docker ps -q这样做是一样的,但是输出条带化为仅包含container_id。docker ps -a列出所有容器(是否在运行)。docker ps -qa然后是所有容器docker ps -q的简单列表,而是正在运行的容器的简单列表。docker ps -q -f name=ContainerName然后是名称为ContainerName的运行中容器的简单列表。docker ps -qa -f也会包含退出的容器,因此逻辑必须是检查-a(是否正在运行),然后不使用-a来检查它是否不仅存在而且还在运行(并且需要首先停止)。


1
if [[ $(sudo docker inspect --format . <container-name>) == "." ]]; then
  docker run <container-name>;
fi

说明

已经有类似的回应。这里的区别是--format .选项(您也可以使用-f .)。这将从检查命令中删除所有详细信息。Docker使用go模板格式,在这种情况下,这意味着它将将其无法识别的任何内容复制到输出中。

因此,如果退出具有该namex的容器,-f itIsThere则将返回itIsThere。如果不是,则docker将返回错误代码和消息(Error: No such object: <container-name>)。

我在詹金斯的日志中找到了这个。


0

@带@FernandoCésar。
这将从给定的容器名称中检查容器ID,并抑制错误输出(2> /dev/null)。

CONTAINER_NAME="awesome-container"

CONTAINER_ID=$(docker inspect --format="{{.Id}}" ${CONTAINER_NAME} 2> /dev/null)
if [[ "${CONTAINER_ID}" ]]; then
  # container found.
else
  # container not found.
fi

0

在bash脚本中,我检查容器是否按如下名称存在:

CONTAINER_NAME="my-container-name"
if ! docker container ls -a | grep -Fq "$CONTAINER_NAME" 1>/dev/null; then
echo "could not found container $CONTAINER_NAME..."
fi

0

-a如果要列出所有状态(已停止,正在运行等)
-f status=running(如果只列出正在运行的容器,则不需要)

$ docker ps -f name=containerName | grep containerName

如果有1行或更多行,则命令的状态码将为0。如果没有容器,则grep将以1状态码结尾。您可以通过以下方式处理它:

视窗

$ echo %errorlevel%

的Linux

$ echo $?

容器启动并运行

容器停止时

查看execSync的属性 参考:https : //www.cyberciti.biz/faq/linux-bash-exit-status-set-exit-statusin-bash/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.