Thinking of Docker's Union File System that any change will actually be carried on the current image (the top-most layer) and not the previous ones; The question is why those layers are not destroyed by Docker and just hidden? Is there any specific reason to it?
caching
by saving each layer individually, docker can cache the result and re-use it later if it is not invalidated by any previous change.
makes for faster builds, and smaller over-all file system use when having multiple images build from the same base image
Docker was built on AUFS which is a union file system.
Images are created by layering changes on top of each other via AUFS (other methods have been added since then)
A typical build will RUN something that creates some data and it save in a layer.
RUN touch a -- L1 a
RUN touch b -- L2 b
RUN touch c -- L3 c
Each layer stores only it's own set of changes.
The sum of these AUFS layers are mounted one on top of each to become the underlying virtual file system for a container. The "Image" is just a view of the data in the underlying layers.
The image itself doesn't store any data. It only references layers which store data.
*image view a b c
L3 c
L2 b
L1 a
The container changes are then made in a layer on top of all this. Copying up any existing data from the appropriate layer if it needs to me modified, adding new data into it's layer, or "removing" data which removes the reference to the data, not the actual data in the underlying layer.
If I was to modify a file, create a file, and remove a file
echo test >> a
touch d
rm c
The layers would look like:
Lcontainer a * d
L3 c
L2 b
L1 a
If you were to destroy one of the lower layers, the view that is presented to the container would be missing that data.
*image view a c
L3 c
L1 a
As Derick Bailey mentions this allows for some clever image build time caching that allows layers to be shared between images, if the exact same layer is used again. This is normally when you build FROM an existing image.
Newer storage drivers like decivemapper and zfs implement the same strategy but do so at the block level with file system snapshots or clones for each layer. Disk blocks that are unchanged from an underlying layer/snapshot will read from the original layer/snapshot. The container layer/snapshot maintains a pointer back to the original data until it is changed or removed.