docker

Luciano Laratelli 2024-07-02T12:13:04.534829Z

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!

tvaughan 2024-07-02T12:43:22.397979Z

Could it be that deps.edn changed which would cause subsequent layers to be rebuilt?

tvaughan 2024-07-02T12:45:17.577569Z

I also seem to remember that most examples I’ve seen online of how to build an uberjar include a clean step

Luciano Laratelli 2024-07-02T13:15:28.554389Z

> 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 redownloading

seancorfield 2024-07-02T17:08:26.737319Z

Your 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.

👀 1
Luciano Laratelli 2024-07-02T17:38:39.216149Z

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}))

seancorfield 2024-07-02T17:47:20.777249Z

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.

Luciano Laratelli 2024-07-02T18:05:37.784669Z

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!