diff --git a/src/docker_clojure/config.clj b/src/docker_clojure/config.clj index abcbce31..50f2d4f1 100644 --- a/src/docker_clojure/config.clj +++ b/src/docker_clojure/config.clj @@ -22,11 +22,15 @@ (s/def ::distro qualified-keyword?) (s/def ::distros (s/coll-of ::distro :distinct true :into #{})) -(s/def ::build-tool (s/or ::specific-tool ::non-blank-string - ::all-tools #(= ::core/all %))) +(s/def ::build-tool keyword?) (s/def ::build-tool-version (s/nilable (s/and ::non-blank-string #(re-matches #"[\d\.]+" %)))) -(s/def ::build-tools (s/map-of ::build-tool ::build-tool-version)) +(s/def ::installer-hash ::non-blank-string) +(s/def ::version ::build-tool-version) +(s/def ::build-tools (s/map-of ::build-tool + (s/keys :req-un [::version ::installer-hash]))) + + (s/def ::maintainers (s/coll-of ::non-blank-string :distinct true :into #{})) @@ -71,17 +75,13 @@ 17 :ubuntu/jammy :default :debian/bookworm}) -(def build-tools - {"lein" "2.11.2" - "tools-deps" "1.11.1.1435"}) - -(def default-build-tool "tools-deps") +(def ^:dynamic *build-tools* + {:lein {:version "2.11.2" + :installer-hash "28a1a62668c5f427b413a8677e376affaa995f023b1fcd06e2d4c98ac1df5f3e"} + :tools-deps {:version "1.11.1.1435" + :installer-hash "7edee5b12197a2dbe6338e672b109b18164cde84bea1f049ceceed41fc4dd10a"}}) -(def installer-hashes - {"lein" {"2.11.1" "03b3fbf7e6fac262f88f843a87b712a2b37f39cffc4f4f384436a30d8b01d6e4" - "2.11.2" "28a1a62668c5f427b413a8677e376affaa995f023b1fcd06e2d4c98ac1df5f3e"} - "tools-deps" {"1.11.1.1429" "bf08cfeb007118b7277aa7423734f5d507604b868f7fc44c0f9929ca9cd94ed4" - "1.11.1.1435" "7edee5b12197a2dbe6338e672b109b18164cde84bea1f049ceceed41fc4dd10a"}}) +(def default-build-tool :tools-deps) (def exclusions ; don't build these for whatever reason(s) #{; no more focal builds for JDK 20+ diff --git a/src/docker_clojure/core.clj b/src/docker_clojure/core.clj index a1e2a384..33990e7a 100644 --- a/src/docker_clojure/core.clj +++ b/src/docker_clojure/core.clj @@ -56,7 +56,7 @@ m)) (defn variant-map [[base-image jdk-version distro - [build-tool build-tool-version]]] + [build-tool build-tool-info]]] (let [variant-arch (get cfg/distro-architectures (-> distro namespace keyword)) base {:jdk-version jdk-version @@ -65,34 +65,31 @@ jdk-version distro) :distro distro :build-tool build-tool - :build-tool-version build-tool-version + :build-tool-version (:version build-tool-info) :maintainer (str/join " & " cfg/maintainers)}] - (-> base - (assoc :docker-tag (default-docker-tag base)) - (assoc-if #(nil? (:build-tool-version base)) :build-tool-versions - cfg/build-tools) - (assoc-if #(seq variant-arch) :architectures variant-arch)))) + (cond-> base + true (assoc :docker-tag (default-docker-tag base)) + variant-arch (assoc :architectures variant-arch)))) (defn pull-image [image] (sh "docker" "pull" image)) -(defn generate-dockerfile! [installer-hashes variant] +(defn generate-dockerfile! [variant] (let [build-dir (df/build-dir variant) filename "Dockerfile"] (log "Generating" (str build-dir "/" filename)) - (df/write-file build-dir filename installer-hashes variant) + (df/write-file build-dir filename variant) (assoc variant - :build-dir build-dir - :dockerfile filename))) + :build-dir build-dir + :dockerfile filename))) -(defn build-image - [installer-hashes {:keys [docker-tag base-image architectures] :as variant}] +(defn build-image [{:keys [docker-tag base-image architectures] :as variant}] (let [image-tag (str "clojure:" docker-tag) _ (log "Pulling base image" base-image) _ (pull-image base-image) {:keys [dockerfile build-dir]} - (generate-dockerfile! installer-hashes variant) + (generate-dockerfile! variant) host-arch (let [jvm-arch (System/getProperty "os.arch")] (if (= "aarch64" jvm-arch) @@ -126,33 +123,24 @@ (defn image-variant-combinations [base-images jdk-versions distros build-tools] - (reduce - (fn [variants jdk-version] - (concat - variants - (let [jdk-base-images (get-or-default base-images jdk-version)] - (loop [[bi & r] jdk-base-images - acc #{}] - (let [vs (combo/cartesian-product #{bi} - #{jdk-version} - (get-or-default distros bi) - build-tools) - acc' (concat acc vs)] - (if (seq r) - (recur r acc') - acc')))))) - #{} jdk-versions)) + (mapcat + (fn [jdk-version] + (let [jdk-base-images (get-or-default base-images jdk-version)] + (mapcat #(combo/cartesian-product #{%} + #{jdk-version} + (get-or-default distros %) + build-tools) + jdk-base-images))) + jdk-versions)) (defn image-variants [base-images jdk-versions distros build-tools] - (into #{} + (into [] (comp (map variant-map) (remove #(= ::s/invalid (s/conform ::variant %)))) - (conj - (image-variant-combinations base-images jdk-versions distros - build-tools) - latest-variant))) + (image-variant-combinations base-images jdk-versions distros + build-tools))) (defn rand-delay "Runs argument f w/ any supplied args after a random delay of 100-1000 ms" @@ -162,27 +150,26 @@ (apply f args))) (defn build-images - [parallelization installer-hashes variants] + [parallelization variants] (log "Building images" parallelization "at a time") (let [variants-ch (to-chan! variants) builds-ch (chan parallelization)] ;; Kick off builds with a random delay so we don't have Docker race ;; conditions (e.g. build container name collisions) (async/thread (pipeline-blocking parallelization builds-ch - (map (partial rand-delay build-image - installer-hashes)) + (map (partial rand-delay build-image)) variants-ch)) (while (> ["git" "rev-parse" "HEAD"] (apply sh) :out) @@ -238,9 +225,9 @@ (let [variants (generate-variants args)] (case cmd :clean (df/clean-all) - :dockerfiles (generate-dockerfiles! cfg/installer-hashes variants) + :dockerfiles (generate-dockerfiles! variants) :manifest (-> variants sort-variants (generate-manifest! args)) - :build-images (build-images parallelization cfg/installer-hashes variants))) + :build-images (build-images parallelization variants))) (logger/stop)) (defn -main diff --git a/src/docker_clojure/dockerfile.clj b/src/docker_clojure/dockerfile.clj index ab3321fe..1b81c1ab 100644 --- a/src/docker_clojure/dockerfile.clj +++ b/src/docker_clojure/dockerfile.clj @@ -1,38 +1,17 @@ (ns docker-clojure.dockerfile (:require + [clojure.java.io :as io] [clojure.java.shell :refer [sh]] [clojure.string :as str] - [docker-clojure.dockerfile.lein :as lein] - [docker-clojure.dockerfile.tools-deps :as tools-deps] + [docker-clojure.dockerfile.combined :as combined] [docker-clojure.dockerfile.shared :refer [copy-resource-file! entrypoint]])) (defn build-dir [{:keys [base-image-tag jdk-version build-tool]}] - (str/join "/" ["target" - (str (str/replace base-image-tag ":" "-") - (when-not (str/includes? base-image-tag (str jdk-version)) - (str "-" jdk-version))) - (if (= :docker-clojure.core/all build-tool) - "latest" - build-tool)])) - -(defn all-prereqs [dir variant] - (tools-deps/prereqs dir variant)) - -(defn all-contents [installer-hashes variant] - (concat - ["" "### INSTALL LEIN ###"] - (lein/install - installer-hashes - (assoc variant :build-tool-version - (get-in variant [:build-tool-versions "lein"]))) - ["" "### INSTALL TOOLS-DEPS ###"] - (tools-deps/install - installer-hashes - (assoc variant :build-tool-version - (get-in variant [:build-tool-versions "tools-deps"]))) - [""] - (entrypoint variant) - ["" "CMD [\"-M\", \"--repl\"]"])) + (io/file "target" + (str (str/replace base-image-tag ":" "-") + (when-not (str/includes? base-image-tag (str jdk-version)) + (str "-" jdk-version))) + (name build-tool))) (defn copy-java-from-temurin-contents [{:keys [jdk-version] :as _variant}] @@ -41,43 +20,30 @@ "ENV PATH=\"${JAVA_HOME}/bin:${PATH}\"" ""]) -(defn contents [installer-hashes {:keys [build-tool distro] :as variant}] - (str/join "\n" - (concat [(format "FROM %s" (:base-image-tag variant)) - ""] - (case (-> distro namespace keyword) - (:debian :debian-slim) (copy-java-from-temurin-contents variant) - []) - (case build-tool - :docker-clojure.core/all (all-contents installer-hashes variant) - "lein" (lein/contents installer-hashes variant) - "tools-deps" (tools-deps/contents installer-hashes variant))))) +(defn contents [{:keys [distro base-image-tag] :as variant}] + (->> (concat [(format "FROM %s" base-image-tag) + ""] + (case (-> distro namespace keyword) + (:debian :debian-slim) (copy-java-from-temurin-contents variant) + []) + (combined/contents variant)) + (str/join "\n"))) -(defn shared-prereqs [dir {:keys [build-tool]}] +(defn do-prereqs [dir {:keys [build-tool] :as variant}] (let [entrypoint (case build-tool - "tools-deps" "clj" - :docker-clojure.core/all "clj" - build-tool)] + :tools-deps "clj" + :lein "lein")] (copy-resource-file! dir "entrypoint" #(str/replace % "@@entrypoint@@" entrypoint) - #(.setExecutable % true false)))) - -(defn do-prereqs [dir {:keys [build-tool] :as variant}] - (shared-prereqs dir variant) - (case build-tool - :docker-clojure.core/all (all-prereqs dir variant) - "lein" (lein/prereqs dir variant) - "tools-deps" (tools-deps/prereqs dir variant))) - -(defn write-file [dir file installer-hashes variant] - (let [{:keys [exit err]} (sh "mkdir" "-p" dir)] - (if (zero? exit) - (do - (do-prereqs dir variant) - (spit (str/join "/" [dir file]) - (str (contents installer-hashes variant) "\n"))) - (throw (ex-info (str "Error creating directory " dir) - {:error err}))))) + #(.setExecutable % true false))) + (copy-resource-file! dir "rlwrap.retry" identity + #(.setExecutable % true false))) + +(defn write-file [^java.io.File dir file variant] + (.mkdirs dir) + (do-prereqs dir variant) + (spit (io/file dir file) + (str (contents variant) "\n"))) (defn clean-all [] (sh "sh" "-c" "rm -rf target/*")) diff --git a/src/docker_clojure/dockerfile/combined.clj b/src/docker_clojure/dockerfile/combined.clj new file mode 100644 index 00000000..d580ddab --- /dev/null +++ b/src/docker_clojure/dockerfile/combined.clj @@ -0,0 +1,43 @@ +(ns docker-clojure.dockerfile.combined + (:require + [docker-clojure.dockerfile.lein :as lein] + [docker-clojure.dockerfile.shared :as shared] + [docker-clojure.dockerfile.tools-deps :as tools-deps])) + +(def distro-deps + {:debian-slim {:build #{"curl" "gnupg"} + :runtime #{"rlwrap" "make" "git"}} + :debian {:build #{"curl" "gnupg"} + :runtime #{"rlwrap" "make" "git"}} + :ubuntu {:build #{"gnupg"} + ;; install curl as a runtime dep b/c we need it at build time + ;; but upstream includes it so we don't want to uninstall it + :runtime #{"rlwrap" "make" "git" "curl"}} + :alpine {:build #{"curl" "tar" "gnupg" "openssl" "ca-certificates"} + :runtime #{"bash" "make" "git"}}}) + +(defn install [variant] + (concat + (lein/env-preamble) + (tools-deps/env-preamble) + ["" + "WORKDIR /tmp" + ""] + (shared/multiline-RUN + (concat (shared/install-distro-deps distro-deps variant) + (lein/installation-commands) + (tools-deps/installation-commands) + (shared/uninstall-distro-build-deps distro-deps variant))) + [""] + (lein/installation-postamble) + (tools-deps/installation-postamble))) + +(defn contents [{:keys [build-tool] :as variant}] + (concat (install variant) + [""] + (shared/entrypoint variant) + (case build-tool + :lein (lein/command variant) + :tools-deps (tools-deps/command variant)))) + +#_(contents {:build-tool :lein, :build-tool-version "2.11.2", :jdk-version 17}) diff --git a/src/docker_clojure/dockerfile/lein.clj b/src/docker_clojure/dockerfile/lein.clj index 7ef65573..7fc7bf5e 100644 --- a/src/docker_clojure/dockerfile/lein.clj +++ b/src/docker_clojure/dockerfile/lein.clj @@ -1,84 +1,43 @@ (ns docker-clojure.dockerfile.lein - (:require [clojure.string :as str] - [docker-clojure.dockerfile.shared - :refer [concat-commands entrypoint install-distro-deps - uninstall-distro-build-deps]])) - -(defn prereqs [_ _] nil) - -(def distro-deps - {:debian-slim {:build #{"wget" "gnupg"} - :runtime #{}} - :debian {:build #{"wget" "gnupg"} - :runtime #{"make"}} - :ubuntu {:build #{"wget" "gnupg"} - :runtime #{"make"}} - :alpine {:build #{"tar" "gnupg" "openssl" "ca-certificates"} - :runtime #{"bash"}}}) - -(def install-deps (partial install-distro-deps distro-deps)) - -(def uninstall-build-deps (partial uninstall-distro-build-deps distro-deps)) - -(def ^:const old-key "6A2D483DB59437EBB97D09B1040193357D0606ED") -(def ^:const new-key "9D13D9426A0814B3373CF5E3D8A8243577A7859F") - -(defn gpg-key - [version] - (let [[major minor] (map #(Integer/parseInt %) (str/split version #"\."))] - (cond - (< 2 major) new-key - (and (= 2 major) (< 10 minor)) new-key - :else old-key))) - -(defn install [installer-hashes {:keys [build-tool-version] :as variant}] - (let [install-dep-cmds (install-deps variant) - uninstall-dep-cmds (uninstall-build-deps variant)] - (-> [(format "ENV LEIN_VERSION=%s" build-tool-version) - "ENV LEIN_INSTALL=/usr/local/bin/" - "" - "WORKDIR /tmp" - "" - "# Download the whole repo as an archive" - "RUN set -eux; \\"] - (concat-commands install-dep-cmds) - (concat-commands - ["mkdir -p $LEIN_INSTALL" - "wget -q https://codeberg.org/leiningen/leiningen/raw/tag/$LEIN_VERSION/bin/lein-pkg" - "echo \"Comparing lein-pkg checksum ...\"" - "sha256sum lein-pkg" - (str "echo \"" (get-in installer-hashes ["lein" build-tool-version]) " *lein-pkg\" | sha256sum -c -") - "mv lein-pkg $LEIN_INSTALL/lein" - "chmod 0755 $LEIN_INSTALL/lein" - "export GNUPGHOME=\"$(mktemp -d)\"" - "export FILENAME_EXT=jar" ; used to be zip but hopefully it's always jar now? - (str "gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys " - (gpg-key build-tool-version)) - "wget -q https://codeberg.org/leiningen/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT" - "wget -q https://codeberg.org/leiningen/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT.asc" - "echo \"Verifying file PGP signature...\"" - "gpg --batch --verify leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT.asc leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT" - "gpgconf --kill all" - "rm -rf \"$GNUPGHOME\" leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT.asc" - "mkdir -p /usr/share/java" - "mv leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT /usr/share/java/leiningen-$LEIN_VERSION-standalone.jar"] - (empty? uninstall-dep-cmds)) - (concat-commands uninstall-dep-cmds :end) - (concat - ["" - "ENV PATH=$PATH:$LEIN_INSTALL" - "ENV LEIN_ROOT 1" - "" - "# Install clojure 1.11.1 so users don't have to download it every time" - "RUN echo '(defproject dummy \"\" :dependencies [[org.clojure/clojure \"1.11.1\"]])' > project.clj \\" - " && lein deps && rm project.clj"]) - - (->> (remove nil?))))) + (:require + [clojure.string :as str] + [docker-clojure.config :as cfg])) + +(def ^:const gpg-key "9D13D9426A0814B3373CF5E3D8A8243577A7859F") + +(defn env-preamble [] + [(format "ENV LEIN_VERSION=%s" (-> cfg/*build-tools* :lein :version)) + "ENV LEIN_INSTALL=/usr/local/bin/" + "ENV LEIN_ROOT=1" + "ENV PATH=$PATH:$LEIN_INSTALL"]) + +(defn installation-commands [] + ["echo Installing Leiningen" + "mkdir -p $LEIN_INSTALL" + "curl -fsSLO https://codeberg.org/leiningen/leiningen/raw/tag/$LEIN_VERSION/bin/lein-pkg" + "echo \"Comparing lein-pkg checksum ...\"" + "sha256sum lein-pkg" + (format "echo \"%s *lein-pkg\" | sha256sum -c -" + (-> cfg/*build-tools* :lein :installer-hash)) + "mv lein-pkg $LEIN_INSTALL/lein" + "chmod 0755 $LEIN_INSTALL/lein" + "export GNUPGHOME=\"$(mktemp -d)\"" + (format "gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys %s" + gpg-key) + "curl -fsSLO https://codeberg.org/leiningen/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.jar" + "curl -fsSLO https://codeberg.org/leiningen/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.jar.asc" + "echo \"Verifying Leiningen file PGP signature...\"" + "gpg --batch --verify leiningen-$LEIN_VERSION-standalone.jar.asc leiningen-$LEIN_VERSION-standalone.jar" + "gpgconf --kill all" + "rm -rf \"$GNUPGHOME\" leiningen-$LEIN_VERSION-standalone.jar.asc" + "mkdir -p /usr/share/java" + "mv leiningen-$LEIN_VERSION-standalone.jar /usr/share/java/leiningen-$LEIN_VERSION-standalone.jar" + "mkdir -p ~/.lein/"]) + +(defn installation-postamble [] + []) (defn command [{:keys [jdk-version]}] (if (>= jdk-version 16) ["CMD [\"repl\"]"] ["CMD [\"lein\", \"repl\"]"])) - -(defn contents [installer-hashes variant] - (concat (install installer-hashes variant) [""] (entrypoint variant) (command variant))) diff --git a/src/docker_clojure/dockerfile/shared.clj b/src/docker_clojure/dockerfile/shared.clj index 5ab360fd..12600ef3 100644 --- a/src/docker_clojure/dockerfile/shared.clj +++ b/src/docker_clojure/dockerfile/shared.clj @@ -2,14 +2,10 @@ (:require [clojure.string :as str] [clojure.java.io :as io])) -(defn concat-commands [base cmds & [end?]] - (let [commands (if end? - (butlast cmds) - cmds)] - (concat base - (map #(str % " && \\") - commands) - (when end? [(last cmds)])))) +(defn multiline-RUN [commands] + (concat ["RUN set -eux; \\"] + (map #(str % " && \\") (butlast commands)) + [(last commands)])) (defn get-deps [type distro-deps distro] (some->> distro namespace keyword (get distro-deps) type)) @@ -22,31 +18,28 @@ (set (concat (build-deps distro-deps distro) (runtime-deps distro-deps distro)))) -(defn install-distro-deps [distro-deps {:keys [distro]}] - (let [deps (all-deps distro-deps distro)] - (when (seq deps) - (case (-> distro namespace keyword) - (:debian :debian-slim :ubuntu) - ["apt-get update" - (str/join " " (concat ["apt-get install -y"] deps)) - "rm -rf /var/lib/apt/lists/*"] +(defn- cmd [& args] + (str/join " " (flatten args))) - :alpine - [(str/join " " (concat ["apk add --no-cache"] deps))] +(defn install-distro-deps [distro-deps {:keys [distro]}] + (when-let [deps (seq (all-deps distro-deps distro))] + (case (-> distro namespace keyword) + (:debian :debian-slim :ubuntu) + ["apt-get update" + (cmd "apt-get install -y" deps) + "rm -rf /var/lib/apt/lists/*"] - nil)))) + :alpine + [(cmd "apk add --no-cache" deps)]))) (defn uninstall-distro-build-deps [distro-deps {:keys [distro]}] - (let [deps (build-deps distro-deps distro)] - (when (seq deps) - (case (-> distro namespace keyword) - (:debian :debian-slim :ubuntu) - [(str/join " " (concat ["apt-get purge -y --auto-remove"] deps))] - - :alpine - [(str/join " " (concat ["apk del"] deps))] + (when-let [deps (seq (build-deps distro-deps distro))] + (case (-> distro namespace keyword) + (:debian :debian-slim :ubuntu) + [(cmd "apt-get purge -y --auto-remove" deps)] - nil)))) + :alpine + [(cmd "apk del" deps)]))) (defn copy-resource-file! "Copy a file named `filename` from resources to a specified `build-dir`. @@ -66,9 +59,7 @@ "This is the same for every build-tool so far, so it's in here. If that changes move it into the build-tool-specific namespaces (or future protocol)." [{:keys [jdk-version]}] - (if (>= jdk-version 16) - (concat - ["COPY entrypoint /usr/local/bin/entrypoint"] - [""] - ["ENTRYPOINT [\"entrypoint\"]"]) - nil)) + (when (>= jdk-version 16) + ["COPY entrypoint /usr/local/bin/entrypoint" + "" + "ENTRYPOINT [\"entrypoint\"]"])) diff --git a/src/docker_clojure/dockerfile/tools_deps.clj b/src/docker_clojure/dockerfile/tools_deps.clj index f5105cec..3889465f 100644 --- a/src/docker_clojure/dockerfile/tools_deps.clj +++ b/src/docker_clojure/dockerfile/tools_deps.clj @@ -1,62 +1,28 @@ (ns docker-clojure.dockerfile.tools-deps - (:require [docker-clojure.dockerfile.shared - :refer [concat-commands copy-resource-file! entrypoint - install-distro-deps uninstall-distro-build-deps]])) - -(defn prereqs [dir _variant] - (copy-resource-file! dir "rlwrap.retry" identity - #(.setExecutable % true false))) - -(def distro-deps - {:debian-slim {:build #{"curl"} - :runtime #{"rlwrap" "make" "git"}} - :debian {:build #{"curl"} - :runtime #{"rlwrap" "make" "git"}} - :ubuntu {:build #{} - ;; install curl as a runtime dep b/c we need it at build time - ;; but upstream includes it so we don't want to uninstall it - :runtime #{"rlwrap" "make" "git" "curl"}} - :alpine {:build #{"curl"} - :runtime #{"bash" "make" "git"}}}) - -(def install-deps (partial install-distro-deps distro-deps)) - -(def uninstall-build-deps (partial uninstall-distro-build-deps distro-deps)) - -(def docker-bug-notice + (:require + [docker-clojure.config :as cfg])) + +(defn env-preamble [] + [(format "ENV CLOJURE_CLI_VERSION=%s" (-> cfg/*build-tools* :tools-deps :version))]) + +(defn installation-commands [] + ["echo Installing tools.deps" + "curl -fsSLO https://download.clojure.org/install/linux-install-$CLOJURE_CLI_VERSION.sh" + "sha256sum linux-install-$CLOJURE_CLI_VERSION.sh" + (format "echo \"%s *linux-install-$CLOJURE_CLI_VERSION.sh\" | sha256sum -c -" + (-> cfg/*build-tools* :tools-deps :installer-hash)) + "chmod +x linux-install-$CLOJURE_CLI_VERSION.sh" + "./linux-install-$CLOJURE_CLI_VERSION.sh" + "rm linux-install-$CLOJURE_CLI_VERSION.sh" + "clojure -e \"(clojure-version)\""]) + +(defn installation-postamble [] ["# Docker bug makes rlwrap crash w/o short sleep first" "# Bug: https://github.com/moby/moby/issues/28009" - "# As of 2021-09-10 this bug still exists, despite that issue being closed"]) - -(defn install [installer-hashes {:keys [build-tool-version] :as variant}] - (let [install-dep-cmds (install-deps variant) - uninstall-dep-cmds (uninstall-build-deps variant)] - (-> [(format "ENV CLOJURE_VERSION=%s" build-tool-version) - "" - "WORKDIR /tmp" - "" - "RUN \\"] - (concat-commands install-dep-cmds) - (concat-commands - ["curl -fsSLO https://download.clojure.org/install/linux-install-$CLOJURE_VERSION.sh" - "sha256sum linux-install-$CLOJURE_VERSION.sh" - (str "echo \"" (get-in installer-hashes ["tools-deps" build-tool-version]) " *linux-install-$CLOJURE_VERSION.sh\" | sha256sum -c -") - "chmod +x linux-install-$CLOJURE_VERSION.sh" - "./linux-install-$CLOJURE_VERSION.sh" - "rm linux-install-$CLOJURE_VERSION.sh" - "clojure -e \"(clojure-version)\""] (empty? uninstall-dep-cmds)) - (concat-commands uninstall-dep-cmds :end) - (concat [""] docker-bug-notice - ["COPY rlwrap.retry /usr/local/bin/rlwrap"]) - (->> (remove nil?))))) + "# As of 2021-09-10 this bug still exists, despite that issue being closed" + "COPY rlwrap.retry /usr/local/bin/rlwrap"]) (defn command [{:keys [jdk-version]}] (if (>= jdk-version 16) ["CMD [\"-M\", \"--repl\"]"] [(str "CMD [\"clj\"]")])) - -(defn contents [installer-hashes variant] - (concat (install installer-hashes variant) - [""] - (entrypoint variant) - (command variant))) diff --git a/src/docker_clojure/manifest.clj b/src/docker_clojure/manifest.clj index 7adb77f0..511cf1ad 100644 --- a/src/docker_clojure/manifest.clj +++ b/src/docker_clojure/manifest.clj @@ -6,21 +6,20 @@ (defn variant-tags "Generates all the Docker Hub tag variations for the given variant" [variant] - (let [short-tag (:docker-tag variant) - full-tag (full-docker-tag variant) - base (into #{} [short-tag full-tag])] - (-> base - (conj - (docker-tag {:omit-jdk? true} variant) - (docker-tag {:omit-build-tool? true} variant) - (docker-tag {:omit-build-tool-version? true} variant) - (docker-tag {:omit-distro? true} variant) - (docker-tag {:omit-distro? true, :omit-build-tool-version? true} variant) - (docker-tag {:omit-jdk? true, :omit-build-tool-version? true} variant) - (docker-tag {:omit-jdk? true, :omit-distro? true - :omit-build-tool-version? true} variant)) - vec - sort))) + (->> [[] ; temurin-21-lein-2.11-bookworm + [:omit-jdk?] ; lein-2.11-bookworm + [:omit-distro?] ; temurin-21-lein-2.11 + [:omit-build-tool?] ; temurin-21-bookworm + [:omit-build-tool-version?] ; temurin-21-lein-bookworm + [:omit-jdk? :omit-distro?] ; lein-2.11 + [:omit-jdk? :omit-build-tool-version?] ; lein-bookworm + [:omit-distro? :omit-build-tool] ; temurin-21 + [:omit-distro? :omit-build-tool-version?] ; temurin-21-lein + [:omit-jdk? :omit-distro? :omit-build-tool?] ; latest + ] + (map #(docker-tag (zipmap % (repeat true)) variant)) + distinct + sort)) (defn variant->manifest [variant] @@ -52,4 +51,3 @@ (map variant->manifest variants) [nil])))) - diff --git a/src/docker_clojure/util.clj b/src/docker_clojure/util.clj index cbe128be..d65ab27f 100644 --- a/src/docker_clojure/util.clj +++ b/src/docker_clojure/util.clj @@ -14,40 +14,35 @@ (= (first (get-or-default cfg/base-images jdk-version)) base-image)) nil - (str - (case base-image - ("eclipse-temurin" "debian") "temurin" - base-image) - "-" jdk-version))) + (str "temurin-" jdk-version))) (defn docker-tag "Returns the Docker tag for the given variant with truthy keys from first arg left out when possible." - [{:keys [omit-all? omit-jdk? omit-build-tool? omit-build-tool-version? - omit-distro?]} + [{:keys [omit-jdk? omit-build-tool? omit-build-tool-version? omit-distro?]} {:keys [base-image jdk-version distro build-tool build-tool-version] :as _variant}] - (if (= ::core/all build-tool) - "latest" - (let [jdk (jdk-label (or omit-all? omit-jdk?) - jdk-version base-image) - dd (get-or-default cfg/default-distros jdk-version) - distro-label (if (and (or omit-all? omit-distro?) (= dd distro)) - nil - (when distro (name distro))) - tag-elements (remove nil? [jdk distro-label]) - build-tool-label (if (and (seq tag-elements) ; ensure tag is non-empty - (or omit-all? omit-build-tool?) - (= build-tool cfg/default-build-tool)) - nil - build-tool) - build-tool-version-label (if (or omit-all? omit-build-tool? - omit-build-tool-version?) - nil - build-tool-version)] - (str/join "-" (remove nil? [jdk build-tool-label - build-tool-version-label - distro-label]))))) + (let [default-distro (get-or-default cfg/default-distros jdk-version) + distro-label (if (and omit-distro? (= default-distro distro)) + nil + (name distro)) + build-tool-label (if (and omit-build-tool? + (= build-tool cfg/default-build-tool)) + nil + (name build-tool)) + build-tool-version-label (if (or omit-build-tool? omit-build-tool-version?) + nil + build-tool-version) + jdk (jdk-label (and omit-jdk? + ;; Can't let distro be the only tag. + (or (nil? distro-label) build-tool-label)) + jdk-version base-image) + tags (remove nil? [jdk build-tool-label build-tool-version-label + distro-label])] + (if (seq tags) + (str/join "-" tags) + ;; No tags means we are tagging "latest". + "latest"))) (def full-docker-tag (partial docker-tag {}))