Bust cache bust within Dockerfile without providing external build args
Update: Reviewing this one, it looks like you injected the cache busting option incorrectly in two ways:
ENV
is not anARG
- The
$(x)
syntax is not a variable expansion, you need curly brackets (${}
), not parenthesis ($()
).
To break the cache on the next run line, the syntax is:
ARG CACHE_BUST
RUN echo "command with external dependencies"
And then build with:
docker build --build-arg CACHE_BUST=$(date +%s) .
Why does that work? Because during the build, the values for ARG
are injected into RUN
commands as environment variables. Changing an environment variable results in a cache miss on the new build.
To bust the cache, one of the inputs needs to change. If the command being run is the same, the cache will be reused even if the command has external dependencies that have changed, since docker cannot see those external dependencies.
Options to work around this include:
- Passing a build arg that changes (e.g. setting it to a date stamp).
- Changing a file that gets included into the image with COPY or ADD.
- Running your build with the
--no-cache
option.
Since you do not want to do option 1, there is a way to do option 3 on a specific line, but only if you can split up your Dockerfile into 2 parts. The first Dockerfile has all the lines as you have today up to the point you want to break the cache. Then the second Dockerfile has a FROM line to depend on the first Dockerfile, and you build that with the --no-cache
option. E.g.
Dockerfile1:
FROM base
RUN normal steps
Dockerfile2
FROM intermediate
RUN curl external.jar>file.jar
RUN other lines that cannot be cached
CMD your cmd
Then build with:
docker build -f Dockerfile1 -t intermediate .
docker build -f Dockerfile2 -t final --no-cache .
The only other option I can think of is to make a new frontend with BuildKit that allows you to inject an explicit cache break, or unique variable that results in a cache break.
You can add ADD
layer with the downloading of some dynamic page from stable source in the beginning of Dockerfile
. Image will be always re-built without using a cache.
Just an example of Dockerfile
:
FROM alpine:3.9
ADD https://google.com cache_bust
RUN apk add --no-cache wget
p.s. I believe you are aware of docker build --no-cache
option.