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

ksh*_*hah 53 bash docker

在Jenkins机器上,我想创建一个具有指定名称的docker容器,只有它尚不存在(在shell脚本中).我想我可能会运行命令来创建容器,如果有的话会忽略失败,但这会导致我的jenkins作业失败.

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

fer*_*rdy 100

你可以通过grepping for a检查是否存在正在运行的容器,<name>并在以后启动它,如下所示:

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

更好:

使用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
Run Code Online (Sandbox Code Playgroud)

  • 如果您有两个名称相似的容器,则此响应不起作用.例如:cool.project(容器1)和dashboard.cool.project(容器2) (7认同)
  • `docker ps -aq -f name=^name$` 将仅匹配确切的名称 (4认同)
  • 对 - 您需要`-a`或尝试运行已退出的容器将失败. (2认同)
  • @MaximTkach这就是为什么使用第二种方法更好,您可以在 docker ps 命令中完全限定容器的名称。但您也可以在 grep 命令中引入正则表达式来查找名称前后的空格。这个测试是故意留给读者的。 (2认同)
  • WiRai的答案更短,没有任何与grep相关的问题 (2认同)

anu*_*ava 27

您可以使用filterformat查看选项docker ps命令,以避免与UNIX的实用工具,比如管道grep,awk等等.

name='nginx'

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

  • 这将匹配部分字符串,但您可以与`--filter"name = ^/$ name $"完全匹配 (5认同)
  • @bcoughlan 第一个“$”是将“name”替换为名为“name”的 shell 变量的值。该变量是在之前定义的。`"name=^/$name$"` 相当于 `"name=^/${name}$"` (在我看来,后者更具可读性)。 (3认同)
  • 真的很棒又简单!谢谢! (2认同)
  • @CiroSantilli新疆改造中心六四事件法轮功它似乎没有记录在docker ps文档中.该字符串被Docker解释为正则表达式,'/'字符在名称中,虽然我不确定是否/为什么需要第一个`$`. (2认同)

小智 21

我想

docker container inspect <container-name> || docker run...
Run Code Online (Sandbox Code Playgroud)

既然docker container inspect调用会设置$?如果容器不存在(不能检查),则为1;如果确实存在,则为0(这意味着已停止的容器).因此,只有在容器不按预期存在的情况下才会调用run命令.

  • 我甚至会使用`docker container inspect <container-name >>>/dev/null 2>&1`来丢弃成功和不成功的输出. (7认同)

rai*_*bba 9

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

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
Run Code Online (Sandbox Code Playgroud)

我不得不搜索太多次,因为即使上面的 100 多个答案实际上也不起作用。我认为原因是对docker ps的误解。docker ps列出正在运行的容器。docker ps -q执行相同的操作,但输出被条带化以仅包含 container_id。docker ps -a列出所有容器(运行或未运行)。docker ps -qathen 是所有容器的简单列表,而docker ps -q是正在运行的容器的简单列表。docker ps -q -f name=ContainerName然后是一个名为 ContainerName 的正在运行的容器的简单列表。docker ps -qa -f也将包括退出的容器,因此逻辑必须是检查 -a (是否存在,是否正在运行),然后不使用 -a 来查看它是否不仅存在,而且正在运行(并且需要首先停止)。


yuc*_*cer 6

只需在名称前加上^ /,后缀加上$.它似乎是一个正则表达式:

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
Run Code Online (Sandbox Code Playgroud)


Cir*_*四事件 6

^$没有无证行为的强大 grep

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

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

理由:

  1. 如果容器名称是另一个容器中的子字符串,则/sf/answers/2700348101/不起作用
  2. /sf/answers/3162011261//sf/answers/3024184271/依赖于我找不到文档的行为: 的退出状态docker container inspect-f name需要一些正则表达式种类。

Python

为了方便起见,我最终在项目中使用了 Python 版本:

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


Bla*_*ise 5

使用docker top更短:

docker top <name> || docker run --name <name> <image>
Run Code Online (Sandbox Code Playgroud)

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