I have been playing around with creating docker files and reading the documentation and I was wondering this question: Does adding an EXPOSE
command to my Doc
Yes, every instruction in a Dockerfile generates a new layer for the resulting image.
However, layers created via EXPOSE
are empty layers. That is, their size is 0 bytes.
While they don't impact you storage-wise, they do count for leveraging layer cache while building or pulling/pushing images from a registry.
A good way to understand an image's layers is to use the docker history
command. For instance, given the following Dockerfile:
FROM scratch
EXPOSE 4000
EXPOSE 3000
do
docker build -t test/image .
If you then docker history test/image
you'll see:
IMAGE CREATED CREATED BY SIZE COMMENT
ab9f435de7bc 4 seconds ago /bin/sh -c #(nop) EXPOSE 4000/tcp 0 B
15e09691c313 5 seconds ago /bin/sh -c #(nop) EXPOSE 3000/tcp 0 B
If you switch the order of the EXPOSE
statements and build again, you'll see the layer cache being ignored.
No, directive EXPOSE
does not add a new layer. This information will be stored permanently in the image and container config and could be retrieved via:
docker inspect --format '{{.Config.ExposedPorts}}' <image_id>
But you may still be wondering why there is a line in the output that says that the new image was created for this command. Consider this Dockerfile
:
FROM alpine
EXPOSE 8000
In the end, Docker produces such output:
Step 1/2 : FROM alpine
---> 965ea09ff2eb
Step 2/2 : EXPOSE 8000
---> Running in 6c8fae4f3499
Removing intermediate container 6c8fae4f3499
---> 067aa2abe94f
Successfully built 067aa2abe94f
Successfully tagged envtest:latest
In the same time docker history
outlines:
IMAGE CREATED CREATED BY SIZE COMMENT
067aa2abe94f About a minute ago /bin/sh -c #(nop) EXPOSE 8000 0B
965ea09ff2eb 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
Every line in the Dockerfile
causes image creation on the top of the current image, thus image has a link to the parent image. Afterward, the immediate container will be initialized based on this new image then your command will be executed within and result committed to the image.
As a general rule, if the command does not lead to changes in the filesystem the new layer won't be created. I would recommend using dive for exploring each layer in a docker image.
I realised i could test this myself. and I've found that adding EXPOSE does not add a new file system layer, but it does add a layer none the less, also it does matter which order you make your docker files for your cache layers.
basically: every command creates a new layer, every command that changes the file system creates a filesystem layer.
FROM ...
EXPOSE 80
COPY smthing .
is different from:
FROM ...
COPY smthing .
EXPOSE 80
When executed multiple times (say in a development environment).
in the first example the EXPOSE
command is cached and is not executed even if the smthing
file changes. If the something file changes, docker build
will only re-executed this command (rest is taken from cache).
In the second example. if the smthing
file changes, the EXPOSE command will also be rebuild. (since everything after the copy command is invalidated and re executed on docker build
).
Would i change the EXPOSE port the first case would have to re-execute the copy command, where the second example wouldn't.
But both would lead to the exact same end result file-system layer wise.
docker inspect imageName #shows the file system layer
docker history imageName #shows all the layers
All instructions create new layers, but instructions that do not change the filesystem will create a layer that is empty.
It's worth looking into how Docker's filesystem layering works which you can read about here or here for AUFS.
Essentially new layers on the file system are made of those files that have changed from the layer below them, it's like a stack of diffs. As such, if there is no change, there is no layer to make. Mostly...
Every instruction in a Dockerfile will create an image layer, but for AUFS (in the case of EXPOSE
) that layer will be empty (no difference between it and the one below it).