# Stage 1: compile the re-frame UI (ui/) to JS. shadow-cljs needs Node and a JVM. It writes # to ../resources/public/js (see ui/shadow-cljs.edn), i.e. /build/resources/public/js here. # trixie, not bookworm: its default-jre is Java 21, which shadow-cljs's Closure Compiler # requires (bookworm's is 17 -> UnsupportedClassVersionError). # ui-base holds what the UI's release build and its tests share: the toolchain and the deps. FROM node:22-trixie-slim AS ui-base RUN apt-get update \ && apt-get install -y --no-install-recommends default-jre-headless \ && rm -rf /var/lib/apt/lists/* WORKDIR /build/ui COPY ui/package.json ui/package-lock.json ./ RUN npm ci # Resolve the ClojureScript deps in their own layer so source edits don't re-download them. COPY ui/shadow-cljs.edn ./ RUN npx shadow-cljs classpath > /dev/null FROM ui-base AS ui COPY shared /build/shared COPY ui/src ./src RUN npx shadow-cljs release app # The UI's tests, not part of the server image: `docker build --target ui-test` # (script/docker-ui-test, script/docker-ui-coverage). Running the container runs the tests; # `npm run coverage` (script/docker-ui-coverage) also writes the report to /build/target/coverage/ui. FROM ui-base AS ui-test COPY ui/.c8rc.json ./ COPY shared /build/shared COPY ui/src ./src COPY ui/test ./test CMD ["npm", "test"] # Stage 2: the server. # JDK 21+ is required by the MCP server (plumcp runs on virtual threads). FROM clojure:temurin-21-tools-deps RUN apt-get update && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Aliases whose deps get pre-fetched into the image; the coverage compose override adds `cov`. ARG DEPS_ALIASES=run COPY deps.edn ./ RUN clojure -P -X:${DEPS_ALIASES} \ && echo "[build] cached jars: $(find /root/.m2 -name '*.jar' | wc -l)" COPY . . COPY --from=ui /build/resources/public/js resources/public/js EXPOSE 3000 CMD ["clojure", "-X:run"]