After read the above doc, I tested to prove the following statement:
Only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not increase the size of the build.
My envs are:
❯ sw_vers
ProductName: macOS
ProductVersion: 11.6.1
BuildVersion: 20G224
❯ docker version
Client:
Cloud integration: v1.0.22
Version: 20.10.13
API version: 1.41
Go version: go1.16.15
Git commit: a224086
Built: Thu Mar 10 14:08:44 2022
OS/Arch: darwin/amd64
Context: default
Experimental: true
Server: Docker Desktop 4.6.1 (76265)
Engine:
Version: 20.10.13
API version: 1.41 (minimum version 1.12)
Go version: go1.16.15
Git commit: 906f57f
Built: Thu Mar 10 14:06:05 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.5.10
GitCommit: 2a1d4dbdb2a1030dc5b01e96fb110a9d9f150ecc
runc:
Version: 1.0.3
GitCommit: v1.0.3-0-gf46b6ba
docker-init:
Version: 0.19.0
GitCommit: de40ad0
❯ dive --version
dive 0.10.0
# installed from brew
Following Dockerfile, using to test, cotains all instruction but it doesn't make sense quietly(Some of them are not used, so it does not cover all possibilities maybe):
# syntax=docker/dockerfile:1
FROM alpine:3.15.4
LABEL name=layer
EXPOSE 3456
ENV APP=layer
ADD add.tar.gz /
COPY copy /copy
ENTRYPOINT ["date"]
RUN rm /bin/arch
CMD ["--help"]
VOLUME /log
USER root
ARG workdir
WORKDIR $workdir
ONBUILD RUN echo 'b'
STOPSIGNAL SIGTERM
HEALTHCHECK CMD which date
SHELL ["/bin/sh", "-c"]
Build and inspect the image, the name as layer
, it has 5 layers:
# Preparation: create build contexts for ADD and COPY
> mkdir add
> dd if=/dev/urandom of=add/1 bs=1M count=1
> dd if=/dev/urandom of=add/2 bs=1M count=1
> dd if=/dev/urandom of=copy bs=1M count=1
> tar -cf add.tar add
> gzip add.tar
# Build
❯ docker build --build-arg workdir=/etc -t layer .
(...eliding)
# Inspect
❯ docker inspect layer | jq '.[0].RootFS.Layers | length'
5
Inspect with dive
, there are unexpected instructions which make layers, FROM
and WORKDIR
:
# the left pane of `dive layer'
┃ ● Layers ┣ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ │
Cmp Size Command
5.6 MB FROM 8792aa27a60beb9
2.1 MB ADD add.tar.gz / # buildkit
1.0 MB COPY copy /copy # buildkit
0 B RUN /bin/sh -c rm /bin/arch # buildkit
0 B WORKDIR /etc
Except RUN, ADD and COPY, there is other instructions that create a image layer?
- For FROM, it seem reasonable somehow
- But for WORKDIR, Why? Can I get the references about it?
+ Like dive
, how could I map between the image layer digest and the command each ?
❯ docker inspect layer | jq '.[0].RootFS.Layers[]'
"sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628"
"sha256:38df8fd6b1d0100d029b0cfa3611ee48cf2d0e2d71856dab9b3c818ae180e100"
"sha256:deab9dc570f38644bbad2bb4a9a91ecec8afdbd4dbd7ed3bae4c3c63e84b1924"
"sha256:34b91600d244859b8ce5aaf493bed6c778c933d51d7f72df7f9ab426f55d50db"
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
Update
After the several times of recreating image, it has 4 layers except for WORKDIR. It seems undeterminitic...:
❯ docker inspect layer | jq -r '.[0].RootFS.Layers[]' | wc -l
4
# the leftpane in dive
┃ ● Layers ┣ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━
Cmp Size Command
5.6 MB FROM 8792aa27a60beb9
2.1 MB ADD add.tar.gz / # buildkit
1.0 MB COPY copy /copy # buildkit
0 B RUN /bin/sh -c rm /bin/arch # buildkit
--no-cache
, the result image has same 5 layers, also for the digests. – Oatmeal