add Dockerfile, build support
s-ol
6 months ago
0 | **/node_modules | |
1 | **/resources/public/js | |
2 | **/.cpcache | |
3 | **/.shadow-cljs | |
4 | **/.nrepl-port | |
5 | **/.clj-kondo/.cache | |
6 | **/yarn-error.log | |
7 | **/report.html | |
8 | **/.idea/* | |
9 | !**/.idea/ClojureProjectResolveSettings.xml | |
10 | **/*.iml | |
11 | **/.lsp | |
12 | **/.clj-kondo |
0 | FROM clojure:openjdk-11-tools-deps AS clojure-deps | |
1 | WORKDIR /app | |
2 | COPY deps.edn deps.edn | |
3 | COPY src-build src-build | |
4 | RUN clojure -A:dev -M -e :ok # preload deps | |
5 | RUN clojure -T:build noop # preload build deps | |
6 | ||
7 | FROM clojure:openjdk-11-tools-deps AS build | |
8 | WORKDIR /app | |
9 | COPY --from=clojure-deps /root/.m2 /root/.m2 | |
10 | COPY shadow-cljs.edn shadow-cljs.edn | |
11 | COPY deps.edn deps.edn | |
12 | COPY src src | |
13 | COPY src-build src-build | |
14 | COPY resources resources | |
15 | ARG REBUILD=unknown | |
16 | ARG VERSION | |
17 | RUN clojure -X:build uberjar :jar-name "app.jar" :verbose true :version '"'$VERSION'"' | |
18 | ||
19 | FROM amazoncorretto:11 AS app | |
20 | WORKDIR /app | |
21 | COPY --from=build /app/app.jar app.jar | |
22 | EXPOSE 8080 | |
23 | ARG VERSION | |
24 | ENV VERSION=$VERSION | |
25 | CMD java -DHYPERFIDDLE_ELECTRIC_VERSION=$VERSION -jar app.jar |
4 | 4 | |
5 | 5 | https://user-images.githubusercontent.com/124158/220984721-bd0960da-8d05-49e1-b9b3-a948e942bfc8.mp4 |
6 | 6 | |
7 | # Setup | |
7 | # Setup (development) | |
8 | 8 | |
9 | 9 | ``` |
10 | 10 | $ clj -A:dev -X user/main |
18 | 18 | |
19 | 19 | 👉 App server available at http://0.0.0.0:8080 |
20 | 20 | ``` |
21 | ||
22 | # Building | |
23 | ||
24 | For a manual JAR deployment: | |
25 | ||
26 | ``` | |
27 | $ clj -X:build build-client # release-mode JS client build | |
28 | $ clj -X:build uberjar # server jar build (cleans & builds client) | |
29 | ``` | |
30 | ||
31 | or to create a Docker image: | |
32 | ||
33 | ``` | |
34 | $ docker build --build-arg VERSION=`git describe ...` -t electric-sudoku . | |
35 | ``` |
0 | {:paths ["src"] | |
0 | {:paths ["src" "resources"] | |
1 | 1 | :deps {ch.qos.logback/logback-classic {:mvn/version "1.2.11"} |
2 | com.hyperfiddle/electric {:mvn/version "v2-alpha-60-g4cb70086"} | |
2 | com.hyperfiddle/electric {:mvn/version "v2-alpha-167-gbd475584"} | |
3 | 3 | com.hyperfiddle/rcf {:mvn/version "20220926-202227"} |
4 | 4 | info.sunng/ring-jetty9-adapter {:mvn/version "0.14.3" |
5 | 5 | :exclusions [org.slf4j/slf4j-api |
15 | 15 | thheller/shadow-cljs {:mvn/version "2.20.1"}} |
16 | 16 | :jvm-opts |
17 | 17 | ["-Xss2m" ; https://github.com/hyperfiddle/photon/issues/11 |
18 | "-Dclojure.tools.logging.factory=clojure.tools.logging.impl/slf4j-factory" | |
19 | "-Dlogback.configurationFile=src/logback.xml" | |
20 | "-XX:-OmitStackTraceInFastThrow" ;; RCF | |
21 | "-XX:+UnlockDiagnosticVMOptions" | |
22 | "-XX:+DebugNonSafepoints"] | |
18 | "-XX:-OmitStackTraceInFastThrow"] ;; RCF | |
23 | 19 | :exec-fn user/main |
24 | :exec-args {}}}} | |
20 | :exec-args {}} | |
21 | :build | |
22 | {:extra-paths ["src-build"] | |
23 | :ns-default build | |
24 | :extra-deps {io.github.clojure/tools.build {:git/tag "v0.8.2" :git/sha "ba1a2bf"} | |
25 | io.github.seancorfield/build-clj {:git/tag "v0.8.0" :git/sha "9bd8b8a"} | |
26 | thheller/shadow-cljs {:mvn/version "2.20.1"}} | |
27 | :jvm-opts ["-Xss2m" | |
28 | "-Dclojure.tools.logging.factory=clojure.tools.logging.impl/slf4j-factory" | |
29 | "-Dlogback.configurationFile=src-dev/logback_dev.xml"]}}} |
7 | 7 | </head> |
8 | 8 | <body> |
9 | 9 | <noscript>You need to enable JavaScript to run this app.</noscript> |
10 | <script type="text/javascript" src="/js/main.js"></script> | |
10 | <script type="text/javascript" src="$:hyperfiddle.client.module/main$"></script> | |
11 | 11 | </body> |
12 | 12 | </html> |
8 | 8 | :modules {:main {:entries [user] |
9 | 9 | :init-fn user/start!}} |
10 | 10 | :build-hooks [(shadow.cljs.build-report/hook {:output-to "target/build_report.html"}) |
11 | (user/rcf-shadow-hook)]}}} | |
11 | (user/rcf-shadow-hook)]} | |
12 | :prod {:target :browser | |
13 | :output-dir "resources/public/js" | |
14 | :asset-path "/js" | |
15 | :module-hash-names true | |
16 | :modules {:main {:entries [user] | |
17 | :init-fn user/start!}}}}} |
0 | 0 | (ns app.sudoku |
1 | #?(:cljs (:require-macros app.sudoku) | |
2 | :clj (:import [de.sfuhrm.sudoku Creator])) | |
1 | #?(:clj (:import [de.sfuhrm.sudoku Creator])) | |
3 | 2 | |
4 | 3 | (:require [hyperfiddle.electric :as e] |
5 | 4 | [hyperfiddle.electric-dom2 :as dom] |
0 | (ns prod | |
1 | (:gen-class) | |
2 | (:require app.sudoku ; in prod, load app into server so it can accept clients | |
3 | hyperfiddle.electric-jetty-server)) | |
4 | ||
5 | (def electric-server-config | |
6 | {:host "0.0.0.0", :port 8080, :resources-path "public"}) | |
7 | ||
8 | (defn -main [& args] | |
9 | (hyperfiddle.electric-jetty-server/start-server! electric-server-config)) | |
10 | ||
11 | ; On CLJS side we reuse src/user.cljs for prod entrypoint |
5 | 5 | (def shadow-watch (delay @(requiring-resolve 'shadow.cljs.devtools.api/watch))) |
6 | 6 | |
7 | 7 | (def electric-server-config |
8 | {:host "0.0.0.0", :port 8080, :resources-path "resources/public"}) | |
8 | {:host "0.0.0.0", :port 8080, :resources-path "public"}) | |
9 | 9 | |
10 | 10 | (defn main [& args] |
11 | 11 | (println "Starting Electric compiler and server...") |
24 | 24 | (shadow.cljs.devtools.api/repl :dev) ; shadow server hosts the cljs repl |
25 | 25 | ; connect a second REPL instance to it |
26 | 26 | ; (DO NOT REUSE JVM REPL it will fail weirdly) |
27 | (type 1))⏎ | |
27 | (type 1)) |
0 | (ns user ^:dev/always ; recompile (macroexpand) electric-main when any cljs src changes | |
0 | (ns ^:dev/always user ; recompile (macroexpand) electric-main when any cljs src changes | |
1 | 1 | (:require |
2 | 2 | app.sudoku |
3 | 3 | hyperfiddle.electric |
0 | (ns build | |
1 | "build electric.jar library artifact and demos" | |
2 | (:require [clojure.tools.build.api :as b] | |
3 | [org.corfield.build :as bb] | |
4 | [shadow.cljs.devtools.api :as shadow-api] ; so as not to shell out to NPM for shadow | |
5 | [shadow.cljs.devtools.server :as shadow-server])) | |
6 | ||
7 | ||
8 | (def lib 'com.hyperfiddle/electric) | |
9 | (def version (b/git-process {:git-args "describe --tags --long --always --dirty"})) | |
10 | (def basis (b/create-basis {:project "deps.edn"})) | |
11 | ||
12 | (defn clean [opts] | |
13 | (bb/clean opts)) | |
14 | ||
15 | (def class-dir "target/classes") | |
16 | (defn default-jar-name [{:keys [version] :or {version version}}] | |
17 | (format "target/%s-%s-standalone.jar" (name lib) version)) | |
18 | ||
19 | (defn clean-cljs [_] | |
20 | (b/delete {:path "resources/public/js"})) | |
21 | ||
22 | (defn build-client [{:keys [optimize debug verbose version] | |
23 | :or {optimize true, debug false, verbose false, version version}}] | |
24 | (println "Building client. Version:" version) | |
25 | (shadow-server/start!) | |
26 | (shadow-api/release :prod {:debug debug, | |
27 | :verbose verbose, | |
28 | :config-merge [{:compiler-options {:optimizations (if optimize :advanced :simple)} | |
29 | :closure-defines {'hyperfiddle.electric-client/VERSION version}}]}) | |
30 | (shadow-server/stop!)) | |
31 | ||
32 | (defn uberjar [{:keys [jar-name version optimize debug verbose] | |
33 | :or {version version, optimize true, debug false, verbose false}}] | |
34 | (println "Cleaning up before build") | |
35 | (clean nil) | |
36 | ||
37 | (println "Cleaning cljs compiler output") | |
38 | (clean-cljs nil) | |
39 | ||
40 | (build-client {:optimize optimize, :debug debug, :verbose verbose, :version version}) | |
41 | ||
42 | (println "Bundling sources") | |
43 | (b/copy-dir {:src-dirs ["src" "resources"] | |
44 | :target-dir class-dir}) | |
45 | ||
46 | (println "Compiling server. Version:" version) | |
47 | (b/compile-clj {:basis basis | |
48 | :src-dirs ["src"] | |
49 | :ns-compile '[prod] | |
50 | :class-dir class-dir}) | |
51 | ||
52 | (println "Building uberjar") | |
53 | (b/uber {:class-dir class-dir | |
54 | :uber-file (str (or jar-name (default-jar-name {:version version}))) | |
55 | :basis basis | |
56 | :main 'prod})) | |
57 | ||
58 | (defn noop [_]) ; run to preload mvn deps |