I think the intermediate images are a deliberate feature, at least during Dockerfile development. They serve as a cache of the results at each step, so that expensive steps don't rerun between invocations of the Dockerfile, even if you've been editing later steps.
I'm basing this off the documentation I've read, I haven't tried it myself.
Yes, this is convenient and speeds up Dockerfile development. At the same time, this is an issue when you consider using Docker as a part of your production deployment toolchain. I think both ways should be supported: incremental multi-layered images for development or exploration, and then possibility of creating a single, compact image for lower overhead in deployment. In a perfect world, it would be a switch for `docker build`, but I'm not fluent enough in Go to propose a solution on that side.
Some people have considered another approach: flattening an existing stack of images. Scripts for that are linked from the Docker issue on GitHub. I wasn't able to get any of these working, and the logic behind these seemed quite convoluted.
Still, my script is just a proof of concept - I tried whether it is possible to take the approach I use internally for Docker build scripts, and use it to build Dockerfiles. It seems it's possible, and it delivers good results. Time and actual usage will show whether it's a good idea; if this approach makes sense, it will hopefully make its way to the Docker core, and my hack won't stay relevant for too long.
"Currently the only way to "squash" the image is to create a container from it, export that container into a raw tarball, and re-import that as an image. Unfortunately that will cause all image metadata to be lost, including its history but also ports, env, default command, maintainer info etc. So it's really not great."
I want to inherit from the base image, to keep the shared files actually shared. This is a feature. It's just the dozen layers of that inheritance that bothers me.
well, sometimes you do want a layered image, just not so much layered. For example, most images will be layered on top of a small number of base OS images which you don't want to download all all over again.
a shell command is indeed not really deterministic but docker won't repeat a RUN step as long as it's not preceded by a non-deterministic (for docker) step such as ADD.
So a good way to optimize your Dockerfile is to put commands in an order like:
* dependencies, e.g. apt-get, useradd...
* containers configs PORT, ENV, USER from less likely to change to more likely to change
I'm basing this off the documentation I've read, I haven't tried it myself.