I have docker-compose and Dockerfile:
...
RUN echo date
RUN echo date >> /timestamp.txt
...
and when I delete image and try to create it again I have this message:
#5 [spring-boot-app stage-0 6/9] RUN echo date
#5 CACHED
#6 [spring-boot-app stage-0 7/9] RUN echo date >> /timestamp.txt
#6 CACHED
As I understand docker should not CACHE commands that change result, isn’t it?
I try to make command in Dockerfile with random result and expect that docker will not CACHE it.
2
Answers
Docker’s layer caching is based on only two things:
RUN
command identical to a previous cached command?In your example, the
RUN
command is idempotent: it always creates a file namedtimestamp.txt
containing the single worddate
. Docker can’t easily tell the difference between that and runningdate >/timestamp.txt
; just runningdate
, which doesn’t affect the container filesystem; or what might happen under the hood running build commands likemake
.As a corollary, you should generally arrange your
RUN
commands so that they are do in fact generate the same result from the same input. Don’t for exampleRUN git clone
, which won’t notice if the upstream repository updates.COPY
ing files also affects the layer cache. If the previous layer is cached, thenCOPY
ing identical files into the image produces a cached image. This means that if you change something like a package manager lock file (package-lock.json
,yarn.lock
,mix.lock
,go.mod
,requirements.txt
) it will cause the nextRUN
command that actually does the installation to be re-run.In principle you can
docker build --no-cache
to avoid the layer caching, but this shouldn’t be something you need routinely.First, running
$ echo date
isn’t the same as running$ echo $(date)
or$ echo `date`
. The first command (the one you’re using) prints the literal word "date", while the last two commands print the current timestamp.Second, as a golden rule of Docker, you should always try to implement a
Dockerfile
in such a way that the images you build from it are replicable across different scenarios or platforms (for example, one way to ensure this is by specifying the versions of dependencies). If you don’t try to follow this rule, you will sometimes encounter unexpected results, especially because of the way Docker caching works.Finally, to be more specific, this is what the Docker documentation says:
This means that you must apply strategies to force the re-execution of
RUN
instructions (the link I left mentions several such strategies).But why? Because otherwise Docker would have to execute a
RUN
instruction to know if the corresponding image layer changed or not, which simply destroys the purpose of caching.