【问题标题】:Docker: Stop and delete docker container if it's runningDocker:停止并删除 docker 容器(如果它正在运行)
【发布时间】: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

【问题讨论】:

    标签: bash docker containers


    【解决方案1】:

    你可以使用:

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

    【讨论】:

    • 您好,感谢您提供的答案。您能否稍微扩展一下它的作用。如果我有 app=''some-rabbitmq' 它不喜欢炒作?
    • 它应该与连字符一起使用,我在回答中添加了一些解释。
    • 解决方案太复杂了。第二个答案更好
    • 这是最完整的答案。添加`||的问题true` 是它仍然存在一个带有 docker 错误的 bash 脚本。通过检查容器的 docker 容器列表,您可以保证仅在存在时调用 stop 和 rm,消除错误并允许脚本运行所需的所有容器命令。
    【解决方案2】:

    您可能已经注意到,docker stopdocker 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】:

      如果您想要 stopremove 全部,请将此代码复制到您的 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】:

              在以下场景中:-

              1. Windows 上的 Docker(wsl2)
              2. Jenkins 服务器在同一个窗口上。
              3. 使用 Jenkins 管道构建和运行容器。
              4. 在管道中使用 bat 脚本。

              在这种情况下,您可以使用以下命令来防止构建失败。

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

              【讨论】:

                【解决方案13】:

                在 CI/CD 管道或不需要输出的东西中,我使用的方式是这样的:

                docker rm -f rabbitmq &> /dev/null
                

                但据我所知,&amp;&gt; 不是官方 POSIX 规范的一部分,所以我们应该使用:

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

                -f(强制)在docker rm -f

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

                而不是 docker stop 发送:

                .. SIGTERM,在宽限期之后,SIGKILL

                1&gt; /dev/nul 将输出 1 (stdout) 重定向到 /dev/null2&gt;&amp;1 将错误 2 (stderr) 重定向到相同的“文件”。 &amp; 作为第一个示例重定向 1 和 2。

                要编写真实文件并附加内容,请使用docker rm -f rabbitmq 1&gt;&gt; docker_rabbitmq.txt 2&gt;&amp;1 或不同的文件docker rm -f rabbitmq 1&gt;&gt; docker_rabbitmq_success.txt 2&gt;&gt; docker_rabbitmq_error.txt

                【讨论】:

                  【解决方案14】:

                  试试下面的功能。改编自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"

                  【讨论】:

                    猜你喜欢
                    • 2018-01-03
                    • 1970-01-01
                    • 2020-08-13
                    • 1970-01-01
                    • 2019-08-11
                    • 2016-10-28
                    • 2018-04-13
                    • 2022-06-14
                    • 1970-01-01
                    相关资源
                    最近更新 更多