31 mai 2016

Docker Cleanup

Most Docker newcomers are disappointed when,  at some time, after various experiments with Docker, they hit a no space left on device issue. Docker indeed do store all containers, images and volumes in /var/lib/docker, which can quickly grow to gigabytes.

One can find tons of blog post about how to cleanup this folder. Here I'd like to give my own tips, and to explain them in detail, so you don't run random command found by Googling the Internet.

/var/lib/docker is used to store :

  • docker images
  • docker container descriptors
  • docker networks descriptors
  • docker volumes
  • containers' layers (depends on the storage driver you used. Typically AUFS)

Terminated containers

I use docker a lot to experiment unix commands, so use to run docker run --it ubuntu bash. When you run a container without the --rm option, container still exists on disk after the command complete. So doing this will create tons of containers, and layers for things I modified on container's filesystem. For this reason I created an alias docker-run to ensure I don't forget this option. But this option can't be used with -d (run in background) so I can't use it when I want to run some backend service for testing purpose. 

As the end of the day, I have tons of stopped containers that I don't use anymore, and will just consume disk in /var/lib/docker. So I use this command to run some cleanup :

docker rm -v $(docker ps --filter status=exited -q)

this command do list all exited containers (thanks to status filter), and only dump their ID (-q). This ID list is used by the remove command to cleanup containers, including volumes they where using.

Unused volumes

Volumes ? Yes, when you run a container which has been built with a VOLUME command in it's Dockerfile, docker do implicitly create a volume on disk, and may copy data from container image in this volume. This can result in significant disk consumption. Removing a container with -v option do force docker to remove such volumes. This doesn't apply to bind mount volumes, only to volumes created by docker daemon.

If you already removed your containers without using -v, volumes remain orphaned in /var/lib/docker. You can remove them as well using :

docker volume rm $(docker volume ls -q -f 'dangling=true')

the "dangling" filter do select volumes that aren't referenced by any container.

Note: one can find many scripts to do comparable cleanup by directly making changes to /var/lib/docker. Those script where written before docker volume command was introduced in 1.9. Don't use them. Directly hacking your docker daemon storage isn't a good idea when you have a clean API for this purpose.

Unused images

You can also use a comparable dangling filter with images, this one will detect image layers that are not referenced by a tag, which in many cases is the result of running docker builds.

docker rmi $(sudo docker images -f "dangling=true" -q)

what about obsolete / unused images ?
You can find some script to detect images which aren't used by a container on your system. For production environment this can make sense, but for my workstation this would remove mostly all docker images, as most container I run don't keep running all day long.

Docker doesn't track image use by containers, this issue is tracking attempt to change this, so writing a garbage collector would be simpler. So far I'm using https://github.com/ndeloof/docker-gc to collect image usage based on docker events. Not perfect, but does the job.

Hope this helps.