Hi all, I have a Dockerfile that starts off as follows:
FROM clojure:temurin-21-tools-deps-alpine AS deps
WORKDIR /build
COPY deps.edn /build/deps.edn
RUN clojure -P
# start build
FROM clojure:temurin-21-tools-deps-alpine AS builder
WORKDIR /build
COPY ./ /build
COPY --from=deps /root/.m2 /root/.m2
RUN clojure -T:build uberjar
My intention is for clojure -P to make a cached layer of my deps so docker doesn’t redownload them when building the uberjar if they haven’t changed.
What I’m seeing instead is that clojure -T:build uberjar triggers a (re-)download of dependencies. Is that related to how tools.build works?
Would appreciate any pointers on what I’m doing wrong, thank you in advance!Could it be that deps.edn changed which would cause subsequent layers to be rebuilt?
I also seem to remember that most examples I’ve seen online of how to build an uberjar include a clean step
> Could it be that deps.edn changed which would cause subsequent layers to be rebuilt?
Yes, but not in my case - it’s the same deps.edn with both clojure invocations.
> include a clean step
They do, but at least what I have is just:
(defn clean []
(b/delete {:path "target/classes"})
(b/delete {:path "target/my-jar.jar"}))
I tried removing the b/delete that deletes target/classes but saw the same redownloadingYour clojure -P is only going to download what is in :deps. It won't download what is in your :build alias (which is a LOT of transitive deps).
You need to add clojure -P -A:build in that first step.
I added that, but I’m still seeing Downloading: … from central messages when clojure -T:build uberjar runs.
In case it changes things, here’s the alias in my deps.edn:
:build {:deps {io.github.clojure/tools.build {:mvn/version "0.10.4"}}
:ns-default build}
and uberjar from my build.clj:
(defn uberjar [_]
(clean nil)
(b/copy-dir {:src-dirs ["src" "resources"]
:target-dir class-dir})
(b/compile-clj {:basis @basis
:src-dirs ["src"]
:class-dir class-dir})
(b/uber {:class-dir class-dir
:uber-file jar-file
:basis @basis
:main 'io.my-org.my-project.core}))I just tested this in one of my projects:
• I removed .cpcache an ~/.m2/repository so I could track all downloads
• clojure -P downloaded the core project dependencies (as expected)
• clojure -P -A:build downloaded all the dependencies needed for tools.build (and all the maven stuff etc etc)
• clojure -T:build uberjar downloaded nothing and built my JAR
So I think something's not right about how you're trying to build your layers -- the Clojure parts works just fine.
Thanks for doing that, helpful to know to dig in more to the docker stuff. Always appreciate your time Sean, hope you have a good rest of your week!