Docker:停止并删除 docker 容器(如果它正在运行)
Posted
技术标签:
【中文标题】Docker:停止并删除 docker 容器(如果它正在运行)【英文标题】:Docker: Stop and delete docker container if it's running 【发布时间】:2016-03-17 16:20:14 【问题描述】:如果 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
【问题讨论】:
【参考方案1】:你可以使用:
app="rabbitmq"
if docker ps | awk -v app="$app" 'NR > 1 && $NF == appret=1; exit ENDexit !ret'; then
docker stop "$app" && docker rm -f "$app"
fi
awk
命令从 BASH 的变量 $app
中获取命令行变量 app
NR>1
跳过 docker ps
命令的第一行。
$(NF) == app
比较最后一列NAMES
是否等于app变量
【讨论】:
您好,感谢您提供的答案。您能否稍微扩展一下它的作用。如果我有 app=''some-rabbitmq' 它不喜欢炒作? 它应该与连字符一起使用,我在回答中添加了一些解释。 解决方案太复杂了。第二个答案更好 这是最完整的答案。添加`||的问题true` 是它仍然存在一个带有 docker 错误的 bash 脚本。通过检查容器的 docker 容器列表,您可以保证仅在存在时调用 stop 和 rm,消除错误并允许脚本运行所需的所有容器命令。【参考方案2】:您可能已经注意到,docker stop
和 docker rm
在容器不存在或未运行时退出并带有指示失败的状态代码。这会导致您的构建失败。
如果您可以处理构建日志中的错误消息,您可以使用这个小技巧来防止 shell 命令失败:
docker stop rabbitmq || true && docker rm rabbitmq || true
在 docker 命令之一失败的情况下,true
会被调用,它总是退出并显示成功的状态码。
【讨论】:
仍然返回容器不存在的错误信息,但状态码表示成功。我的竹管道过程没有失败,所以它对我有用。 这将在容器已经被移除时生成Error response from daemon: no such id: rabbitmq
。
@anubhava:正确。正如答案中已经提到的:“诀窍”是忽略 docker 命令的返回值。如果您需要一个没有错误消息的“干净”解决方案,您需要检查容器是否存在。
对我来说,这个命令不再起作用了,它曾经起作用,但现在它不起作用了……这是否发生在其他人身上?
您可以使用--rm
运行容器,然后使用docker stop container_name || true
停止。它会自行移除。【参考方案3】:
我有类似的问题,但不喜欢接受的答案,因为它会抑制命令中的所有错误,而不仅仅是“未找到”错误。
但是,docker ps -q --filter "name=rabbitmq"
仅在该名称的容器实际存在时才会产生输出,因此受到Test if a command outputs an empty string 的启发,我想出了:
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
我的实际用例是定义一对 Ansible 任务,这些任务从早期任务中生成的名称列表中删除所有当前存在的容器(无论是否正在运行):
- 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
【讨论】:
我发现使用docker ps -aq ...
很有用。 -a
选项意味着它还将找到存在但当前未运行的容器。
很好的答案,我只是在 bash 脚本中使用了它,如果它已经在运行,让它重新启动 docker 容器。正如@PeterBloomfield 所建议的,也使用了ps -aq
。
如果找不到容器,grep -q .
也有一个非零存在代码,因此你的整个行。所以这仍然会导致错误。这将迫使我附加|| echo 'not found'
或类似的东西。到那时,接受的答案并没有太大区别
为避免过滤器影响整个命令返回码,您可以将其重构为 if 语句:if docker ps -q --filter "name=rabbitmq" | grep -q .; then docker stop rabbitmq && docker rm -fv rabbitmq; fi
我从 docker ps -qa --filter
开始,以确保任何崩溃的容器也能显示出来。【参考方案4】:
这是我停止和删除 docker 容器的首选方式。 true 的管道是为了确保它始终输出成功。没有它,如果容器名称不存在,任何 bash 脚本都会退出并出错。
docker rm -f container_name || true
【讨论】:
docker rm -f container_name &>/dev/null && echo 'Removed old container'
docker container rm | Docker Documentation: 强制删除正在运行的容器(使用 SIGKILL)。
您可以使用--rm
运行容器,然后使用docker stop container_name || true
停止。【参考方案5】:
要先停止所有容器,您必须使用
停止所有容器docker kill $(docker ps -q)
并删除所有容器
docker rm $(docker ps -a -q)
如果你想删除所有图像,这是命令
docker rmi $(docker images -q)
【讨论】:
您不能在共享环境中执行此操作。图片您有两个正在运行的管道。【参考方案6】:# 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
【讨论】:
【参考方案7】:如果您想要 stop
和 remove
全部,请将此代码复制到您的 script.sh 中
#!/bin/sh
ids=$(docker ps -a -q)
for id in $ids
do
echo "$id"
docker stop $id && docker rm $id
done
【讨论】:
【参考方案8】:如果您不删除已停止的容器,另一种解决此问题的简单方法是依赖docker ps -a
,它将始终返回该容器 ID。然后在该停止的容器上执行docker stop
将幂等地什么都不做:
docker stop $(docker ps -a --filter name= rabbitmq -q )
【讨论】:
【参考方案9】:我建议在 bash 中使用这个咒语:
( docker stop $CONTAINER > /dev/null && echo Stopped container $CONTAINER && \
docker rm $CONTAINER ) 2>/dev/null || true
它总是以 0 退出,如果容器没有运行,它不会抱怨,如果它真的停止了,它会打印 Stopped container $CONTAINER
。
【讨论】:
Clean tear down,如果没有找到容器,它会静默“失败”,但如果找到容器,则不会静默stop
/rm
容器。【参考方案10】:
这里基于一些答案的一般形式:
docker rm -f container_name > /dev/null 2>&1 && echo 'removed container' || echo 'nothing to remove'
【讨论】:
【参考方案11】:解决这个问题的简单方法
docker container ls -al | grep <name> && docker container rm -f <name>
【讨论】:
【参考方案12】:在以下场景中:-
-
Windows 上的 Docker(wsl2)
Jenkins 服务器在同一个窗口上。
使用 Jenkins 管道构建和运行容器。
在管道中使用 bat 脚本。
在这种情况下,您可以使用以下命令来防止构建失败。
'docker stop rabbitmq && docker rm rabbitmq || exit 0;'
【讨论】:
【参考方案13】:在 CI/CD 管道或不需要输出的东西中,我使用的方式是这样的:
docker rm -f rabbitmq &> /dev/null
但据我所知,&>
不是官方 POSIX 规范的一部分,所以我们应该使用:
docker rm -f rabbitmq 1> /dev/null 2>&1
-f
(强制)在docker rm -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
。
【讨论】:
【参考方案14】:试试下面的功能。改编自https://***.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"
【讨论】:
以上是关于Docker:停止并删除 docker 容器(如果它正在运行)的主要内容,如果未能解决你的问题,请参考以下文章