The intermediate image is mentioned in docker doc many times,
Only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not increase the size of the build.
from ENV section, it mentions intermediate layer,
Each ENV line creates a new intermediate layer, just like RUN commands. This means that even if you unset the environment variable in a future layer, it still persists in this layer and its value can’t be dumped. You can test this by creating a Dockerfile like the following, and then building it.
So I follow the example,
FROM alpine
ENV ADMIN_USER="mark"
RUN echo $ADMIN_USER > ./mark
RUN unset ADMIN_USER
and build the image and run history,
$ docker history 37c8ebdf36fd
IMAGE CREATED CREATED BY SIZE COMMENT
37c8ebdf36fd 12 seconds ago /bin/sh -c unset ADMIN_USER 0B
789dc0df2bb8 13 seconds ago /bin/sh -c echo $ADMIN_USER > ./mark 5B
8fc06b8bf4a3 15 seconds ago /bin/sh -c #(nop) ENV ADMIN_USER=mark 0B
e7d92cdc71fe 2 months ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
$ docker run --rm test sh -c 'echo $ADMIN_USER'
mark
I have several questions,
- The variable should be unset by later layers (RUN unset), why it's still there?
from docker inspect, I found where ENV is stored,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"ADMIN_USER=mark"
],
"Cmd": [
"/bin/sh",
"-c",
"unset ADMIN_USER"
],
If the container starts, it first exports ADMIN_USER=mark and then unset it, the env var ADMIN_USER should not exist.
This means that even if you unset the environment variable in a future layer, it still persists in this layer and its value can’t be dumped.
The doc explains it, but I'm confused. Since the layer is 0B, I assume there's nothing stored in that layer.
- what are those layers with only 0B size? Why it's not removed from the final image?
Per Docker's image spec via The Moby Project:
Images are composed of layers. Each layer is a set of filesystem changes. Layers do not have configuration metadata such as environment variables or default arguments - these are properties of the image as a whole rather than any particular layer.
layer with 0B should be deleted (because it indicates no fs change), why it's still there?
Since the ENV command layer only defines metadata, why it's represented as a layer in docker history?
what's the difference between the intermediate layer and the image?