How to remove a directory in docker?
When you can't seem to remove a directory, here are two possibilities:
- User confusion between images and containers. Each
docker run
creates a new container, and any changes in containers, like removing a directory, or running something that modifies the file system, are isolated from the original image, and all other containers. - Aufs layering bug/feature. Look at
docker info
to see if you are using Storage Driver aufs or imagemapper. To reinstall docker to use imagemapper: backup any irreplaceable, unique images to tar files, remove docker.io, install lxc-docker from the ppa as described in the official install docs and change/etc/default/docker
to containDOCKER_OPTS="--storage-driver=devicemapper"
It is also probably an anti-pattern to commit directories and then remove them because that data may still be in there somewhere. Even if it disappears from the file system, it could still be wasting space internally.
Docker images are built in layers, each commit is a layer.
To see this, try docker history <image>
to see what is in your image.
The first case is deserving of a short, simple example, but it looks like you are possibly experiencing the second case.
Images vs. Containers and removing directories
Let's create a private image called mystuff
from ubuntu:14.04
and, later below, try to rm -rf /opt:
$ docker run -it ubuntu:14.04 /bin/bash
root@435e68479c5b:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@435e68479c5b:/# exit
$ docker commit 435e6 mystuff
Let's look inside (-t
is only used here for pretty printing on one line):
docker run -t mystuff ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Now let's try to remove /opt
(usually that is optional stuff, safe to remove):
docker run -t mystuff rm -rf /opt
And then look inside for it, and it is still there!!! (seems like the reported problem):
docker run -t mystuff ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
What happened?
- each time
docker run mystuff
is used, it makes a new container from the imagemystuff
- Changes to the image are not committed unless you use docker commit
If you look in the container, the changes are there:
docker ps -a
... lots of stuff...
e9e8be13d928 mystuff:latest "rm -rf /opt" 2 minutes ago Exited (0) 2 minutes ago nostalgic_archimedes
Get a tarball out and look for opt, grep it for dir beginning with opt, it isn't there!:
docker export e9e8 | tar tv | grep ^opt
Note: e9e8
is particular to my run of this example. To refer to a container, you can use part of the hex string from docker ps
in the first col.
Now I commit the container that has the rm -rf change into a new image noopt
:
docker commit e9e8 noopt
And look inside a container created from noopt:
docker run -t noopt ls
bin boot dev etc home lib lib64 media mnt proc root run sbin srv sys tmp usr var
And sure enough, opt is gone!
But because docker images are in layers, distributing noopt will include /opt in an earlier historical image, so you can't keep other people from getting it back:
docker history noopt
IMAGE CREATED CREATED BY SIZE
bc4e69f9e871 59 minutes ago rm -rf /opt 0 B
d198d23dab38 About an hour ago /bin/bash 3 B
04c5d3b7b065 9 days ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B
d735006ad9c1 9 days ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
70c8faa62a44 9 days ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
c7b7c6419568 9 days ago /bin/sh -c #(nop) ADD file:d4aab24fc178303dc0 192.5 MB
511136ea3c5a 18 months ago 0 B
To get back to the layer before /opt was removed, we just need to pick out d198d... and run it
docker run -t d198d23dab38 ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Summary:
- Docker has containers and images.
- Images are intended to be more permanent.
- Images are created in layers called commits, similar in concept to git repositories
- Containers are created from images, and changes in containers are not kept in images (unless explicitly committed)
Docker also has a great build system that should have been used here. Whoever wrote that script should instead learn about docker build
and write a proper Dockerfile