165

I am looking to pragmatically stop and delete a Docker container if it is running. This is for a build script.

Take the following example. How would I stop and delete the Docker container "rabbitmq" as seen under the NAMES column in a bash script?

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 

The following command will delete the container and does what I'm looking to do

docker stop rabbitmq && docker rm -f rabbitmq 

However, it's combing it into a script that I would like to know? I think it would look something like this.

#!/bin/bash if [ /*docker ps check some value */ ]; then docker stop rabbitmq && docker rm -f rabbitmq fi 

16 Answers 16

312

As you have probably noticed, docker stop as well as docker rm exit with a status code indicating failure if the container is not existent or not running. This results in your build failing.

If you can cope with the error messages in your build log you can do this little trick to prevent the shell command of failing:

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

In the case that one of the docker command fails, true is called which always exits with a status code indicating success.

Sign up to request clarification or add additional context in comments.

5 Comments

The error message that container doesn't exist is still returned, but the status code is indicating success. My bamboo pipeline process without failing, so it works for me.
This will generate Error response from daemon: no such id: rabbitmq when container has already been removed.
@anubhava: Correct. As already mentioned in the answer: The "trick" is to just ignore the return value of the docker commands. If you need a "clean" solution without error messages you need to check if the container is present.
For me, this command doesn´t work anymore, it used to work but now it doesn´t... Does this happen to anyone else?
You can run container with --rm and just stop with docker stop container_name || true. It will remove itself.
82

I have a similar problem, but didn't like the accepted answer as it suppresses all errors from the commands, rather than just the "not found" error.

However, docker ps -q --filter "name=rabbitmq" only produces output if a container of that name actually exists, so inspired by Test if a command outputs an empty string I came up with:

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

The following command is also useful for testing filter definitions:

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

My actual use case was in defining a pair of Ansible tasks that deleted all currently existing containers (whether running or not) from a list of names generated in an earlier task:

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

I find it useful to use docker ps -aq .... The -a option means it will also find containers which exist but are not currently running.
Excellent answer, I just used this in bash script let it restart the docker container if it's already running. Used ps -aq as well, as suggested by @PeterBloomfield.
if the container is not found, grep -q . also has a nonzero exist code and thus your entire line. So this still results in an error. Which would force me to append || echo 'not found' or something like this. And at that point there is not much of a difference to the accepted answer
To avoid the filter affecting the overall command return code, you could refactor it as an if statement: if docker ps -q --filter "name=rabbitmq" | grep -q .; then docker stop rabbitmq && docker rm -fv rabbitmq; fi
I started this with docker ps -qa --filter to ensure any crashed containers also show up.
46

This is my preferred way to stop and remove a docker container. The piping of true is there to ensure that it always outputs a success. Without it, any bash scripts would exit and error if the container name did not exist.

docker rm -f container_name || true 

4 Comments

docker rm -f container_name &>/dev/null && echo 'Removed old container'
docker container rm | Docker Documentation: Force the removal of a running container (uses SIGKILL).
You can run container with --rm and just stop with docker stop container_name || true.
@igor just found this today. kinda late to the party but running with --rm means you cant take advantage of docker's restart policy. I user restart=unless-stopped which excludes using --rm. --rm seems to be a convenience function for dev purposes. In a deployment, you want docker to try to restart containers after reboot or error conditions
25

A variant of @ncoghlan's answer:

# 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 
  • pipe into xargs is an idiomatic way to use output to construct commands
  • xargs -r avoids running docker commands when no matching container exists
  • first docker ps finds all matching running containers
  • second docker ps finds all matching containers, even not running
  • separate commands make sure the container is removed even if it isn't running

Comments

12

You can use:

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 command gets a command line var app from BASH's variable $app
  • NR>1 skips first header row from docker ps command.
  • $(NF) == app Compare last column NAMES is equal to app variable or not

4 Comments

hi thanks for the answer it does work. Could you expand on what its doing a little bit. If I have app=''some-rabbitmq' it does not like the hypen?
It should work with hyphens, I am adding some explanation in answer.
too complicated of a solution. Second answer is better
This is the most complete answer. the problem with adding ` || true` is that it still exists a bash script with the docker error. by checking the list of docker containers for the container you are guaranteed to only call stop and rm if it exists, eliminating errors and allowing the script to run all of the container commands needed.
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 

Comments

5

I suggest this incantation in bash:

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

It always exits with 0, doesn't complain if the container is not running, and prints Stopped container $CONTAINER if it actually got stopped.

1 Comment

Clean tear down, that "fails" silently if no container is found, but does not silently stop/rm the container if it is found.
4

A general form based on some answers here:

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

Comments

2

Copy this code in your script.sh if you want stop and remove all

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

Comments

2

Try below function. Adapted from 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 } 

Call it: remove_previous_instance "CNAME"

Comments

2

For stop for i in $(docker ps | awk '{print $1}) ; do docker stop "$i"; done

for killing for i in $(docker ps | awk '{print $1}) ; do docker rm "$i"; done

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
1

Easy way to do this issue

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

Comments

1

In the Below scenario:-

  1. Docker on windows(wsl2)
  2. Jenkins server on the same windows.
  3. Using Jenkins pipeline to build and run containers.
  4. Using bat script in the pipeline.

In this case, you can use the below command for preventing the build from failing.

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

Comments

1

In a CI/CD pipeline or something that you don't need the output, the way I use is this:

docker rm -f rabbitmq &> /dev/null 

but as I undertand &> is not part of the official POSIX spec so we shoud use:

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

-f (force) in docker rm -f:

Force the removal of a running container (uses SIGKILL)

instead of docker stop that sends:

.. SIGTERM, and after a grace period, SIGKILL

1> /dev/nul redirect the output 1 (stdout) to /dev/null and 2>&1 redirect the error 2 (stderr) to the same "file". & as the firs example redirect both 1 and 2.

To write a real file and append the content use docker rm -f rabbitmq 1>> docker_rabbitmq.txt 2>&1 or different files docker rm -f rabbitmq 1>> docker_rabbitmq_success.txt 2>> docker_rabbitmq_error.txt.

Comments

0

If you do not delete your stopped containers, another simple way to address this is to rely on docker ps -a, which will always return that container id. Then executing docker stop on that stopped container will idempotently simply do nothing:

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

Comments

-3

to stop all containers first you have to stop all containers with

docker kill $(docker ps -q) 

and to delete all containers

docker rm $(docker ps -a -q) 

and if you want delete all images this is the command

docker rmi $(docker images -q) 

1 Comment

You cannot do this in the shared environment. Image you have two pipelines running.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.