skip to Main Content

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


  1. Docker’s layer caching is based on only two things:

    1. Is the previous layer cached?
    2. If it is, then is this RUN command identical to a previous cached command?

    In your example, the RUN command is idempotent: it always creates a file named timestamp.txt containing the single word date. Docker can’t easily tell the difference between that and running date >/timestamp.txt; just running date, which doesn’t affect the container filesystem; or what might happen under the hood running build commands like make.

    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 example RUN git clone, which won’t notice if the upstream repository updates.

    COPYing files also affects the layer cache. If the previous layer is cached, then COPYing 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 next RUN 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.

    Login or Signup to reply.
  2. 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:

    The cache for RUN instructions isn’t invalidated automatically between
    builds.

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search