停止并删除docker容器(如果正在运行)


79

我正在寻求实用地停止和删除docker容器(如果正在运行)。这是用于构建脚本的。

请看下面的例子。我如何停止和删除docker容器“ rabbitmq”,如bash脚本中的NAMES列所示?

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

Answers:


183

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

如果您可以处理构建日志中的错误消息,则可以执行以下小技巧来防止shell命令失败:

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

如果docker命令之一失败,则将true调用该命令,该命令始终以指示成功的状态代码退出。


仍然返回容器不存在的错误消息,但是状态代码指示成功。我的竹制管道过程没有失败,因此对我有用。
shamanSK

2
Error response from daemon: no such id: rabbitmq当容器已被移除时,将生成此信息。
anubhava

3
@anubhava:是的。正如答案中已经提到的:“技巧”就是忽略docker命令的返回值。如果您需要一个没有错误信息的“干净”解决方案,则需要检查容器是否存在。
Johannes Barop

对我来说,此命令不再起作用,它曾经可以起作用,但是现在它不再起作用了……这对其他任何人都有用吗?
joudaon

37

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

但是,docker ps -q --filter "name=rabbitmq"只有在确实存在该名称的容器时才产生输出,因此受Test启发,如果命令输出了我想出的空字符串

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

5
我觉得使用很有用docker ps -aq ...。该-a选项意味着它还将查找存在但当前未运行的容器。
彼得·布鲁姆菲尔德

很好的答案,我只是在bash脚本中使用过它,如果它已经在运行,它可以重新启动docker容器。也使用ps -aq@PeterBloomfield建议的方法。
Psiloc

如果找不到该容器,则grep -q .还存在一个非零的存在代码,因此还有整行。因此,这仍然会导致错误。这将迫使我追加|| echo 'not found'或类似的东西。那时,所接受的答案
Felix B

为避免过滤器影响整个命令返回代码,可以将其重构为if语句:if docker ps -q --filter "name=rabbitmq" | grep -q .; then docker stop rabbitmq && docker rm -fv rabbitmq; fi
ncoghlan

22

现在使用docker已有一段时间了。这是我停止和删除Docker容器的首选方式。使用true管道可以确保始终输出成功。没有它,如果容器名称不存在,则任何bash脚本都会退出并出错。

docker rm -f container_name || true

10
docker rm -f container_name &>/dev/null && echo 'Removed old container'
filimonov

docker容器rm | Docker文档强制删除正在运行的容器(使用SIGKILL)
詹森·罗

13

您可以使用:

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
  • awk命令app从BASH的变量获取命令行var$app
  • NR>1docker ps命令中跳过第一个标题行。
  • $(NF) == app比较最后一列NAMES是否等于应用程序变量

嗨,谢谢你的回答,它的工作原理。您能否扩展一下它的功能。如果我有app =''some-rabbitmq'',它不喜欢连字符吗?
Robbo_UK 2015年

它应该与连字符一起使用,我在回答中添加了一些解释。
anubhava 2015年

1
解决方案太复杂了。第二个答案更好
Scoota P

2
这是最完整的答案。添加`||的问题 true`是它仍然存在带有docker错误的bash脚本。通过检查容器的docker容器列表,可以确保仅调用stop和rm(如果存在),从而消除错误并允许脚本运行所有需要的容器命令。
AsAP_Sherb '17

7
# 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

4

我建议用bash来表达这个咒语:

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

它始终以0退出,如果容器未在运行,则不会抱怨,并且在容器Stopped container $CONTAINER实际上已停止时显示。


清洁推倒,认为“失败”悄无声息,如果没有容器被发现,但不默默地stop/rm如果发现容器中。
emmagras

2

基于此处一些答案的一般形式:

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


0

如果你想在这个script.sh代码复制stopremove所有

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

0

如果您不删除已停止的容器,则解决此问题的另一种简单方法是依靠docker ps -a,该方法将始终返回该容器ID。然后docker stop在该停止的容器上执行将完全无能为力:

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


-2

要先停止所有容器,您必须先停止所有容器

docker kill $(docker ps -q)

并删除所有容器

docker rm $(docker ps -a -q)

如果要删除所有图像,这是命令

docker rmi $(docker images -q)
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.