Fork me on GitHub
#clojure
<
2023-11-09
>
Noah Bogart14:11:16

for those with clj+cljs applications and using docker, how do you write your dockerfile/docker-compose.yml to have both clojure and node installed? i spent a painful evening last night wrestling with various methods and didn't find anything satisfactory

Noah Bogart14:11:28

The primary issue being that RUN curl -sL | bash - no longer works to install node in a FROM clojure dockerfile

Janet A. Carr14:11:38

Are you building your artifacts in the docker build, or are you just running build artifacts in docker?

Janet A. Carr14:11:03

Docker compose is for running docker images. It sounds like you're trying to build them.

p-himik14:11:25

I use Node inside Docker but outside of the Clojure image (inside Docker - for safety reasons because screw Node and its mistakes) and then simply ptu the built JS bundle into the Clojure container. Couldn't be happier with the setup.

delaguardo14:11:16

Multi stage dockerfile is extremly helpful with this problem:

FROM node:latest AS builder

# Install clojure related tools
RUN ...

# Build artifacts
RUN ...

FROM clojure:latest

COPY --from=builder /path/to/compiled/artifacts /path/to/resources

Janet A. Carr14:11:44

@UEENNMX0T I use the clojure:temurin-20-alpine base image and then install npm with apk. It installs node as an npm dependency. That may or may not work depending on if you need Nodejs 18 specifically.

👍 1
Noah Bogart15:11:12

the docker container currently runs mongo, lein repl, and then two calls to npm to watch changes to the cljs (shadow-cljs), and to watch for changes to the css. that's why i can't just using COPY --from=builder ...

Noah Bogart15:11:08

in the past, i'd run these in a separate tab of my console, but i'm using a new machine and don't feel like setting up all of the extra stuff to get it to work. other devs on our team (open source project) rely on it too

delaguardo15:11:29

you still can run extra commands from separate tab: docker compose exec container -ti npm ...

Noah Bogart15:11:29

i'm looking to be able to run docker compose up -d and then have everything running behind the scenes so all i have to do is jack into the repl

delaguardo15:11:55

this is going against docker principles but you can start container with a chain of commands:

npm ... & \
npm ... & \
lein repl

Zed15:11:03

I'm using clojure:temurin-17-tools-deps-bullseye-slim and then I followed the instructions here for Debian: https://github.com/nodesource/distributions

👍 1
iperdomo17:11:44

there are examples of uber images different tech stacks in the same container (for development) - e.g. https://github.com/penpot/penpot/tree/develop/docker/devenv

👍 1
Chase16:11:20

If you just want a straight hacked up dockerfile here is mine lol: https://github.com/chase-lambert/clojure-app-template/blob/main/Dockerfile

Noah Bogart17:11:57

oh that's very nice, i'll try that out

respatialized17:11:05

(resharing here because #CHV7NHGAG has like 34 people in it)

Alex Miller (Clojure team)17:11:42

Can you share what doesn’t work with data.xml?

Luciano Laratelli18:11:06

I’m seeing this error building my application:

#17 22.79 Syntax error (IOException) compiling fn* at (io/atlantico_software/spanish_publishers/warehouse_location_updates.clj:195:3).
#17 22.79 Filename too long
The line it’s unhappy about is the beginning of a core.match expression. I’ve shortened the filename a few times (down to warehouse.clj) but still seeing the error — is there anything else I should try? Or just keep shortening the name until it accedes?

ghadi18:11:33

it's not the namespace that's the problem

ghadi18:11:44

it's a core.match macro being expanded into something wild

hiredman18:11:15

it is because the name of the class file for the generated code is too long, so the file cannot be written to disk because it exceeds the file name length limit of whatever filesystem you are using

1
hiredman18:11:41

for the classes the compiler generates the namespace name is usually part of, but not the whole class file name, and usually the namespace name ends up being part of the directory tree the class gets written to, but the name itself is something generated by the compiler

hiredman18:11:16

the names generated by the compiler typically reflect the structure of the code, for example a "$fn" will get tacked on for every level of anonymous functions

👀 1
hiredman18:11:58

so particularly hairy very nested expressions can result in long class names

hiredman18:11:22

core.match can generate some rather hairy nested expressions

hiredman18:11:40

additionally sometimes for certain expressions the compiler will insert immediately invoked functions, for example E becomes ((fn [] E)) , which can add nesting where none may be immediately apparent

Luciano Laratelli18:11:58

I see… is there a way to write match expressions to not nest as much? My expression is (to my eyes) pretty simple:

(def almuzara "ALMUZARA")

(defn record->publisher [{:keys [Proveedor Imprint Tema] :as record}]
  (match [Proveedor Imprint Tema]
    ["editorial almuzara" _ _] almuzara
    ;; 27 more lines like the previous
    :else (throw (Exception. (str "Found an unexpected proveedor/imprint/tema combo:" (select-keys record [:Proveedor :Imprint :Tema]))))))

hiredman19:11:18

it is kind of occupational hazard of core.match's implementation, and likely why its use isn't as wide spread as you might expect

hiredman19:11:17

I have a little pattern matching library that never really got a release https://github.com/hiredman/match2/tree/master which is much more naive about how it compiles patterns, and so results in less nesting hairy stuff

Luciano Laratelli19:11:55

I will check that out, thank you for the link and for the explanation!

Lyn Headley00:11:53

Wow. This just scared me away from core.match.

ag23:11:48

There's no way to "consume" an alias loading all the libs defined in :extra-deps without restarting the REPL?

Alex Miller (Clojure team)00:11:37

There is in 1.12! sync-deps to the rescue

💙 1
dpsutton01:11:31

:alpha      {:extra-deps {org.clojure/clojure {:mvn/version "1.12.0-alpha5"}}}
in ~/.clojure/deps.edn is a lovely treat for the new features

ag01:11:06

Whoa, I just tried (sync-deps :aliases [:bench]) and it worked beautifully. I was so excited about add-lib thing that I completely missed awesomeness of sync-deps. Thank you Alex!

seancorfield04:11:42

I have a hot key bound in Calva that prompts for aliases and then does sync-deps 🙃 1.12 is awesome-sauce!

silian15:11:45

Wow, @U04V70XH6, is VS Code your daily driver? If so, I rely on the same text editor as Sean Corfield and that's pretty cool. (Good to be in good company :)

ag15:11:45

> I have a hot key bound in Calva Oh, that'd be nice to have in Emacs. What's the best way of figuring out all available aliases? Including ~/.clojure/deps.edn, etc.? Also, is it possible to (relatively easily to) determine which aliases were loaded? Ideally, it should only prompt with aliases that either not yet loaded, or modified.

Alex Miller (Clojure team)16:11:14

clj -X:deps aliases provides alias info, happy to consider changes if needed

1
seancorfield17:11:29

@U02U1T66REZ All my config is here: https://github.com/seancorfield/vscode-calva-setup (key bindings, settings, Calva REPL snippets, Joyride scripts) plus I use https://github.com/seancorfield/dot-clojure for aliases and for starting my REPL. Here's the alias I use at work for starting a REPL:

:vscode-calva-jack-in
  {:extra-deps {com.datomic/dev.datafy {:git/sha "4a9dffb"
                                        :git/tag "v0.1"
                                        :git/url ""}
                djblue/portal {:mvn/version "0.49.1"
                               #_#_:local/root "/home/sean/oss/portal"}
                io.github.seancorfield/dot-clojure
                {:git/tag "v1.0.2"
                 :git/sha "6a3f903"}
                io.github.stuarthalloway/reflector
                {:git/sha "93a0c19b4526c1180959e940202928d35e5c3cef"}
                jedi-time/jedi-time {:mvn/version "RELEASE"}
                party.donut/dbxray {:mvn/version "RELEASE"}}
and my .vscode/settings.json file at work:
{
  "calva.replConnectSequences": [
    {
      "name": "World Singles Backend (Jack-In)",
      "projectType": "deps.edn",
      "cljsType": "none",
      "autoSelectForJackIn": true,
      "projectRootPath": ["."],
      "menuSelections": {
        "cljAliases": ["build", "dev", "+default", "test", "vscode-calva-jack-in"]
      }
    },
    {
      "name": "World Singles Backend (Connect)",
      "projectType": "deps.edn",
      "cljsType": "none",
      "autoSelectForConnect": true,
      "projectRootPath": ["."]
    }
  ],
  "calva.jackInEnv": {
    "LOG4J_CONFIGURATION_FILE": "log4j2-test.properties"
  },
  "calva.autoConnectRepl": true,
  "workbench.colorTheme": "Default Dark Modern",
  "workbench.preferredDarkColorTheme": "Default Dark Modern",
  "workbench.iconTheme": "vs-seti",
}

2
silian17:11:53

I'm just surprised all the wizards here don't all exclusively use emacs haha

seancorfield17:11:23

I used to. I used Emacs way back in the 17.x days through the early 19.x days. I used Together/J for my Java years (late '90s onward for a while). I picked Emacs back up when I came to Clojure (2010) but never really settled back into it, and after trying tons of configs, I switched to "modern" editors and used a bunch, settling on Atom until I switched to VS Code -- and with cljs customization via Joyride, it's programmable like Emacs, while having great integrations with everything else I use (like Jira/BitBucket at work!). And Calva is awesome, with LSP/clj-kondo for static analysis too.

silian17:11:34

Then we junior devs are lucky beneficiaries! ... I started in Atom and adopted VS Code + Calva after struggling with Proto REPL. Very happy to be here! 🔵:large_green_circle:

ag17:11:51

What does clj -X:deps aliases do under the hood? What's the equivalent for this in the REPL? I'm thinking, if I already have a connected repl, wouldn't be faster/straightforward to send something to the REPL instead?

seancorfield18:11:58

@U02U1T66REZ I really liked Atom + ProtoREPL but it stopped being maintained and updates to Atom broke things. That's when I switched to Chlorine (and a Socket REPL). And then when it looked like Atom would also stop being maintained, I switched to VS Code + Clover (a port of Chlorine), and then Clover sort of stopped being maintained(!) so I switched to Calva... and it happened to coincide with the VS Code version of Portal appearing (which I'd switched to from Reveal, which I'd switched to from REBL 🙂 ).

😂 1
silian18:11:08

Okay, so I think the lesson for me here is that change is the only constant, there is no perfect tool and to stay nimble & tinker often! I like it!

ag20:11:06

I need to add a version that works even if org.clojure/tools.deps.cli is not in the classpath

seancorfield20:11:43

I would expect it to not be on the classpath in general...

👍 1
seancorfield20:11:13

Even the new-in-1.12 stuff that provides access to the CLI tooling stuff does it by shelling out to the actual CLI.

ag20:11:54

I'v fixed the snippet. Now it works even if it's not on the classpath. First, it tries it anyway, since that would be slightly faster