停止并删除正在运行的 Docker 容器

我希望务实地停止和删除一个 Docker 容器,如果它正在运行。这是一个构建脚本。

以下面的例子为例。如何在 bash 脚本中的 NAMES 列下停止并删除 Docker 容器“ rabbitmq”?

docker ps


CONTAINER ID        IMAGE             COMMAND                  CREATED             STATUS              PORTS                   NAMES
9909a5e2856f        rabbitmq-image   "/docker-entrypoint.s"   11 minutes ago      Up 11 minutes       0.0.0.0:5672->5672/tcp, rabbitmq
8990dd1fe503        redis-image      "/entrypoint.sh redis"   6 weeks ago         Up 4 days           0.0.0.0:32770->6379/tcp redis
etc

下面的命令将删除容器并执行我想要执行的操作

docker stop rabbitmq && docker rm -f rabbitmq

但是,它把它整合成了一个我想知道的脚本?我觉得应该是这样的。

#!/bin/bash


if [ /*docker ps check some value */ ]; then
docker stop rabbitmq && docker rm -f rabbitmq
fi
113714 次浏览

你可使用:

app="rabbitmq"
if docker ps | awk -v app="$app" 'NR > 1 && $NF == app{ret=1; exit} END{exit !ret}'; then
docker stop "$app" && docker rm -f "$app"
fi
  • 命令从 BASH 的变量 $app获取命令行 var app
  • NR>1docker ps命令中跳过第一个标题行。
  • 比较最后一列 NAMES是否等于应用程序变量

您可能已经注意到,如果容器不存在或不运行,则 docker stopdocker rm退出时带有状态代码,表示失败。这会导致构建失败。

如果您能够处理构建日志中的错误消息,那么您可以使用下面这个小技巧来防止 shell 命令失败:

docker stop rabbitmq || true && docker rm rabbitmq || true

在其中一个 docker 命令失败的情况下,调用 true,该命令总是退出,并显示一个表示成功的状态代码。

我有一个类似的问题,但不喜欢接受的答案,因为它抑制了来自命令的 所有错误,而不仅仅是“未找到”错误。

然而,docker ps -q --filter "name=rabbitmq"只有在该名称的容器确实存在的情况下才会产生输出,所以受到 测试命令是否输出空字符串的启发,我想出了:

docker ps -q --filter "name=rabbitmq" | grep -q . && docker stop rabbitmq && docker rm -fv rabbitmq

下面的命令对于测试筛选器定义也很有用:

docker ps -q --filter "name=rabbitmq" | grep -q . && echo Found || echo Not Found

我的实际用例是在定义一对 Anable 任务时,该任务从早期任务中生成的名称列表中删除了所有当前存在的容器(不管是否在运行) :

- name: Check for containers that actually exist
shell: 'docker ps -aq --filter "name=\{\{ item }}"'
with_items:
- '\{\{ previous_command.stdout_lines }}'
register: found_containers


- name: Remove the containers found by the above command
shell: 'docker stop \{\{ item.item }} && docker rm -fv \{\{ item.item }}'
with_items: '\{\{ found_containers.results }}'
when: item.stdout

这是我首选的停止和删除码头容器的方法。真实的管道是为了确保它总是输出成功。没有它,如果容器名称不存在,任何 bash 脚本都会退出并出错。

docker rm -f container_name || true

停止所有集装箱首先你必须停止所有集装箱

docker kill $(docker ps -q)

并删除所有容器

docker rm $(docker ps -a -q)

如果你想删除所有的图像,这是命令

docker rmi $(docker images -q)
# Stop and remove containers with names like "rabbitmq" and "rabbitmq123" if they exist
CONTAINER_NAME="rabbitmq"
OLD="$(docker ps --all --quiet --filter=name="$CONTAINER_NAME")"
if [ -n "$OLD" ]; then
docker stop $OLD && docker rm $OLD
fi

如果希望 stopremove都是,请将此代码复制到 script.sh 中

#!/bin/sh
ids=$(docker ps -a -q)
for id in $ids
do
echo "$id"
docker stop $id && docker rm $id
done

如果不删除已停止的容器,解决这个问题的另一个简单方法是依赖于 docker ps -a,它总是返回容器 ID。然后在那个停止的容器上执行 docker stop将等幂地什么也不做:

Docker stop $(docker ps-a —— filter name = rabbitmq-q)

我在 bash 里建议这个咒语:

( docker stop $CONTAINER > /dev/null && echo Stopped container $CONTAINER && \
docker rm $CONTAINER ) 2>/dev/null || true

它总是以0退出,如果容器没有运行,不会抱怨,如果实际停止,则打印 Stopped container $CONTAINER

基于这里的一些答案的一般形式:

docker rm -f container_name > /dev/null 2>&1 && echo 'removed container' || echo 'nothing to remove'

解决这个问题的简单方法

docker container ls -al | grep <name> && docker container rm -f <name>

在下列情况下:-

  1. Docker on windows (wsl2)
  2. Jenkins 的服务器。
  3. 使用 Jenkins 管道构建和运行容器。
  4. 在管道中使用 bat 脚本。

在这种情况下,可以使用下面的命令防止生成失败。

'docker stop rabbitmq && docker rm rabbitmq || exit 0;'

在 CI/CD 流水线或者其他你不需要输出的东西中,我使用的方法是这样的:

docker rm -f rabbitmq &> /dev/null

但据我所知,&>不属于官方 POSIX 规范的一部分,因此我们应该使用:

docker rm -f rabbitmq 1> /dev/null 2>&1

docker rm -f中的 -f(力) :

强制移除正在运行的容器(使用 SIGKILL)

而不是 docker stop发送:

. . SIGTERM,宽限期过后,SIGKILL

1> /dev/nul将输出1(stdout)重定向到 /dev/null,而 2>&1将错误2(stderr)重定向到相同的“文件”。&作为第一个例子重定向1和2。

要写一个真正的文件和附加的内容使用 docker rm -f rabbitmq 1>> docker_rabbitmq.txt 2>&1或不同的文件 docker rm -f rabbitmq 1>> docker_rabbitmq_success.txt 2>> docker_rabbitmq_error.txt

试试下面的功能。改编自 https://stackoverflow.com/a/60579344/1554778

    function remove_previous_instance(){
echo "Container name: $1"
CNAME=$1
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
}

你可以这么说: remove_previous_instance "CNAME"

@ ncoghlan 回答的一个变体:

# stop runnin container(s)
docker ps -q --filter "name=$name" | xargs -r docker stop
# remove existing container(s)
docker ps -aq --filter "name=$name" | xargs -r docker rm
  • 管道到 xargs是使用输出构造命令的惯用方法
  • xargs -r避免在没有匹配的容器时运行 docker 命令
  • 第一个 docker ps查找所有匹配的运行容器
  • 第二个 docker ps查找所有匹配的容器,甚至不运行
  • 单独的命令确保容器被删除,即使它没有运行

为了停下来 For i in $(docker ps | awk’{ print $1}) ; do docker stop“ $i”; done

杀人 For i in $(docker ps | awk’{ print $1}) ; do docker rm“ $i”; done