54

I have script that stops containers and then removes them

docker stop $(docker ps -q)
docker rm $(docker ps -a -q)

But I don't want to remove the docker container with name "my_docker".

How can I remove all containers except this one?

nwinkler
  • 52,665
  • 21
  • 154
  • 168
nick_gabpe
  • 5,113
  • 5
  • 29
  • 38

12 Answers12

64

You can try this, which will

  • Filter out the unwanted item (grep -v), and then
  • returns the first column, which contains the container id

Run this command:

docker rm $(docker ps -a | grep -v "my_docker" | awk 'NR>1 {print $1}')

To use cut instead of awk, try this:

docker rm $(docker ps -a | grep -v "my_docker" | cut -d ' ' -f1)

Examples for awk/cut usage here: bash: shortest way to get n-th column of output

nwinkler
  • 52,665
  • 21
  • 154
  • 168
  • 2
    This also return the column header name (on Windows at least) so it tries to remove the container id "CONTAINER" and display an error. There are no consequences, but for purists like me just remove the first row by using `docker rm $(docker ps -a | grep -v "my_docker" | awk 'NR>1 {print $1}')` :) – Yann39 Aug 10 '18 at 13:29
  • Is there a way to exclude 2 container names? – variable May 05 '20 at 08:45
  • is it possible to stop running containers except one by name ? – Youssef Boudaya Aug 25 '21 at 11:49
  • In case if somebody is also looking for a way to exclude multiple containers, you should use `|` in your pattern: `docker rm $(docker ps -a | grep -v "my_docker1\|my_docker2" | awk 'NR>1 {print $1}')` – Hellaren Jan 28 '23 at 01:34
  • In my case, I had to remove all volumes except for _minikube_, so all I had to do was `docker volume rm -f $(docker volume ls -q | grep -v minikube)`. Pretty sure it'd work with containers too, and I cannot test it because I don't have anything up right now. – Anonymous Person May 10 '23 at 05:27
29

The title of the question asks for images, not containers. For those stumbling across this question looking to remove all images except one, you can use docker prune along with filter flags:

docker image prune -a --force --filter "label!=image_name"

replacing image_name with the name of your image.

You can also use the "until=" flag to prune your images by date.

Cybernetic
  • 12,628
  • 16
  • 93
  • 132
  • 2
    Are you sure that negating on a filter actually works? It does not seem to work. – djuarezg Jul 08 '19 at 14:53
  • 3
    Docker changes their docs every 3.2 seconds so wouldn’t be surprised if it’s now deprecated. Definitely used to work. – Cybernetic Jul 08 '19 at 16:09
  • 2
    This now deletes all images. – JoeAC Mar 12 '20 at 21:55
  • Interestingly the [documentation](https://docs.docker.com/engine/reference/commandline/image_prune/) currently says, "In addition, the confirmation prompt for `docker image prune` always warns that *all* dangling images will be removed, even if you are using `--filter`." – Panzercrisis Jun 15 '20 at 18:12
  • 2
    However the documentation, at least, does seem to still support this answer, regardless of whether or not it actually works. – Panzercrisis Jun 15 '20 at 18:15
  • 5
    In case anyone is wondering on how to test the filter before pruning, use `docker ls`, as in `docker image ls -a --filter "label!=image_name"`. Though, as @djuarez noted, negating the filter does not work, it throws a `Error response from daemon: Invalid filter 'label!'` – Hi-Angel Nov 11 '20 at 15:08
  • 1
    It DOES work as shown in Cybernetic's answer. No errors. Ubuntu 21.04. – IdahoB Aug 19 '21 at 20:32
10

This is what's actually happening docker rm $(List of container Ids). So it's just a matter of how you can filter the List of Container Ids.

For example: If you are looking to delete all the container but one with a specific container Id, then this docker rm $(docker ps -a -q | grep -v "my_container_id") will do the trick.

so-random-dude
  • 15,277
  • 10
  • 68
  • 113
  • 1
    This will not work since `docker ps -a -q` does not print the container name, which means that you can't filter it out using `grep -v`. – nwinkler Nov 22 '16 at 14:37
  • it works if you need to skip one container and delete the rest. To stop "docker stop $(docker ps -a -q | grep -v "my_container_id")" – Aziz Zoaib Jan 06 '19 at 05:57
2

I achieved this by the following command:

docker image rm -f $(docker images -a | grep -v "image_repository_name" | awk 'NR>1 {print $1}')
shakil080
  • 351
  • 2
  • 5
2

For those, who want to exclude more than 1 container just add

grep -v "container_name2" | 

after the grep -v "container_name1" command. The final command might look like

docker rm $(docker ps -a | grep -v "my_docker1" | grep -v "my_docker2" | cut -d ' ' -f1)

lukashino
  • 63
  • 6
1

I would prefer to test the container name using something along the lines of (untested)

docker inspect --format '{{ .Name }}' $(docker ps -aq)

this will give the names of the (running or not) containers, and you can filter and

docker rm

using this information

user2915097
  • 30,758
  • 6
  • 57
  • 59
1

Deletes all the images except node image

sudo docker rmi -f $(sudo docker image ls -a | grep -v "node" | awk 'NR>1 {print $3}')

Firoj Siddiki
  • 1,649
  • 1
  • 20
  • 22
1

Using docker ps with --filter name=<my_docker>

docker rm $(docker ps -a -q | grep -v `docker ps -a -q --filter "name=my_docker"`)
x7qiu
  • 103
  • 1
  • 10
0

Old question, but I like reviving posts.

For such case you could use Spotify's Docker GC: https://github.com/spotify/docker-gc#excluding-containers-from-garbage-collection

You could do:

echo "my_docker" >> /tmp/docker-gc-exclude-containers
echo '*' > /tmp/docker-gc-exclude
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /etc:/etc:ro -v /tmp/docker-gc-exclude-containers:/etc/docker-gc-exclude-containers:ro -v /tmp/docker-gc-exclude:/etc/docker-gc-exclude:ro spotify/docker-gc

(if you would like to get your images cleaned off too, you can avoid mounting the docker-gc-exclude file)

Nico Villanueva
  • 876
  • 8
  • 22
0

To stop

docker stop $(docker ps -a -q | grep -v "my_container_id")

To remove

docker rm $(docker ps -a -q | grep -v "my_container_id")
Aziz Zoaib
  • 661
  • 8
  • 21
0

I know its little late response but it can help any windows user. Here is the command I prepared:

docker rmi $(
docker image list -a --no-trunc --format "table {{.ID}},{{.Repository}}" | 
Where-Object { 
    $_ -NOTMATCH  "mcr.microsoft.com/dotnet/core/aspnet" -and
    $_ -NOTMATCH  "ubuntu" -and
    $_ -NOTMATCH  "busybox" -and
    $_ -NOTMATCH  "alpine"
} | Select-Object -Skip 1 | %{ $_.Split(',')[0];} 

)
Gaurav
  • 782
  • 5
  • 12
-4

Maybe you can start all the containers you don't want to prune. Then, run:

docker container prune -a
Jose Luis
  • 173
  • 1
  • 3