skip to Main Content

I’m running a clojure application which needs to access a local database. The clojure application is using jdbc:

:dependencies [[org.clojure/clojure "1.10.0"]
                 ...
                 [org.clojure/java.jdbc "0.7.12"]
                 [org.postgresql/postgresql "42.3.3"]]

The application works as expected when run directly on a host with a version of postgresql installed, even when connecting to a remote database.

However, when run from within a docker container based on the clojure image:

# syntax=docker/dockerfile:1
   
FROM clojure
WORKDIR /ui-service
COPY . .
CMD ["lein", "ring", "server-headless", "3000"]
EXPOSE 3000

It fails to connect:

lan-activity-ui-service-1  | org.postgresql.util.PSQLException: ERROR: could not load library "/usr/lib/postgresql/13/lib/llvmjit.so": /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /lib/x86_64-linux-gnu/libz3.so.4)
lan-activity-ui-service-1  |            QueryExecutorImpl.java:2675 org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse
lan-activity-ui-service-1  |            QueryExecutorImpl.java:2365 org.postgresql.core.v3.QueryExecutorImpl.processResults
lan-activity-ui-service-1  |             QueryExecutorImpl.java:355 org.postgresql.core.v3.QueryExecutorImpl.execute
lan-activity-ui-service-1  |                   PgStatement.java:490 org.postgresql.jdbc.PgStatement.executeInternal
lan-activity-ui-service-1  |                   PgStatement.java:408 org.postgresql.jdbc.PgStatement.execute
lan-activity-ui-service-1  |           PgPreparedStatement.java:166 org.postgresql.jdbc.PgPreparedStatement.executeWithFlags
lan-activity-ui-service-1  |           PgPreparedStatement.java:118 org.postgresql.jdbc.PgPreparedStatement.executeQuery
lan-activity-ui-service-1  |                          jdbc.clj:1090 clojure.java.jdbc/execute-query-with-params
lan-activity-ui-service-1  |                          jdbc.clj:1084 clojure.java.jdbc/execute-query-with-params
lan-activity-ui-service-1  |                          jdbc.clj:1113 clojure.java.jdbc/db-query-with-resultset*
lan-activity-ui-service-1  |                          jdbc.clj:1093 clojure.java.jdbc/db-query-with-resultset*
lan-activity-ui-service-1  |                          jdbc.clj:1182 clojure.java.jdbc/query
lan-activity-ui-service-1  |                          jdbc.clj:1144 clojure.java.jdbc/query
lan-activity-ui-service-1  |                          jdbc.clj:1160 clojure.java.jdbc/query
lan-activity-ui-service-1  |                          jdbc.clj:1144 clojure.java.jdbc/query
lan-activity-ui-service-1  |                              db.clj:33 ui-service.db/all-devices
lan-activity-ui-service-1  |                              db.clj:32 ui-service.db/all-devices
lan-activity-ui-service-1  |                         handler.clj:21 ui-service.handler/fn
lan-activity-ui-service-1  |                         handler.clj:20 ui-service.handler/fn
lan-activity-ui-service-1  |                           core.clj:158 compojure.core/wrap-response[fn]
lan-activity-ui-service-1  |                           core.clj:128 compojure.core/wrap-route-middleware[fn]
lan-activity-ui-service-1  |                           core.clj:137 compojure.core/wrap-route-info[fn]
lan-activity-ui-service-1  |                           core.clj:146 compojure.core/wrap-route-matches[fn]
lan-activity-ui-service-1  |                           core.clj:185 compojure.core/routing[fn]
lan-activity-ui-service-1  |                          core.clj:2701 clojure.core/some
lan-activity-ui-service-1  |                          core.clj:2692 clojure.core/some
lan-activity-ui-service-1  |                           core.clj:185 compojure.core/routing
lan-activity-ui-service-1  |                           core.clj:182 compojure.core/routing
lan-activity-ui-service-1  |                        RestFn.java:139 clojure.lang.RestFn.applyTo
lan-activity-ui-service-1  |                           core.clj:667 clojure.core/apply
lan-activity-ui-service-1  |                           core.clj:660 clojure.core/apply
lan-activity-ui-service-1  |                           core.clj:192 compojure.core/routes[fn]
lan-activity-ui-service-1  |                           json.clj:102 ring.middleware.json/wrap-json-params[fn]
lan-activity-ui-service-1  |                           json.clj:143 ring.middleware.json/wrap-json-response[fn]
lan-activity-ui-service-1  |                            cors.clj:47 jumblerg.middleware.cors/allow-origins
lan-activity-ui-service-1  |                            cors.clj:41 jumblerg.middleware.cors/allow-origins
lan-activity-ui-service-1  |                            cors.clj:57 jumblerg.middleware.cors/wrap-cors[fn]
lan-activity-ui-service-1  |                           Var.java:384 clojure.lang.Var.invoke
lan-activity-ui-service-1  |                          reload.clj:39 ring.middleware.reload/wrap-reload[fn]
lan-activity-ui-service-1  |                      stacktrace.clj:26 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
lan-activity-ui-service-1  |                      stacktrace.clj:96 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
lan-activity-ui-service-1  |                           jetty.clj:25 ring.adapter.jetty/proxy-handler[fn]
lan-activity-ui-service-1  |                       (Unknown Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle
lan-activity-ui-service-1  |                 HandlerWrapper.java:97 org.eclipse.jetty.server.handler.HandlerWrapper.handle
lan-activity-ui-service-1  |                        Server.java:499 org.eclipse.jetty.server.Server.handle
lan-activity-ui-service-1  |                   HttpChannel.java:311 org.eclipse.jetty.server.HttpChannel.handle
lan-activity-ui-service-1  |                HttpConnection.java:258 org.eclipse.jetty.server.HttpConnection.onFillable
lan-activity-ui-service-1  |            AbstractConnection.java:544 org.eclipse.jetty.io.AbstractConnection$2.run
lan-activity-ui-service-1  |              QueuedThreadPool.java:635 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
lan-activity-ui-service-1  |              QueuedThreadPool.java:555 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
lan-activity-ui-service-1  |                        Thread.java:833 java.lang.Thread.run

How can I ensure the required dependencies are available within the docker container? Do I need to use a multi-stage docker build to include the postgresql image? Or is it possible to add the required dependencies purely in java/clojure?

I was able to build a container including the /usr/lib/postgresql/13/ directory and the /usr/lib/postgresql/13/lib/llvmjit.so file that clojure was looking for, but weirdly I still get the error: ERROR: could not load library "/usr/lib/postgresql/13/lib/llvmjit.so":

# syntax=docker/dockerfile:1
   
FROM postgres:13 as postgres

FROM clojure
WORKDIR /ui-service
COPY . .
COPY --from=postgres /usr/lib/postgresql/ /usr/lib/postgresql/
RUN ls -l /usr/lib/postgresql/13/lib/llvmjit.so
CMD ["lein", "ring", "server-headless", "3000"]
EXPOSE 3000

2

Answers


  1. Although it is possible to pull in dependencies over the network from Clojure using tools like Pomegranate, and a similar capability is available in the alpha releases of Clojure 1.12 itself, it is probably a lot simpler to just build your own container that adds the necessary dependencies to the one you are using.

    Login or Signup to reply.
  2. I have a demo project that shows how to use both Postgres and H2 via Docker container from Clojure. It uses the jdbc.next library.

    Note that we are running Postgres in a Docker container. This demo runs Clojure from the command line. Of course, you could also run Clojure in a container, as long as it can access Postgres over port 5432 as normal.

    Leiningen is used as normal to define the Clojure project and its dependencies:

    (defproject demo "0.1.0-SNAPSHOT"
      :license {:name "Eclipse Public License"
                :url  "http://www.eclipse.org/legal/epl-v10.html"}
    
      :dependencies [
                     [com.h2database/h2 "1.4.200"] ; #todo cannot upgrade yet or crash!
                     [hikari-cp "3.0.1"]
                     [org.clojure/clojure "1.11.1"]
                     [org.clojure/test.check "1.1.1"]
                     [org.postgresql/postgresql "42.6.0"]
                     [prismatic/schema "1.4.1"]
                     [seancorfield/next.jdbc "1.2.659"] ; #todo try porsas
                     [tupelo "23.07.04"]
                     ]
    
      :plugins      [[com.jakemccrary/lein-test-refresh "0.25.0"]
                     [lein-ancient "0.7.0"]
                     ]
    
    <snip>
    )
    

    A short BASH script kicks off Postgres:

    #!/bin/bash
    
    docker run --rm  --name pg-docker  --env POSTGRES_PASSWORD=docker  --detach  --publish 5432:5432  
      -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data    postgres:14
    

    and then run the demo using lein:

    > lein clean ; lein test
    
    -----------------------------------
       Clojure 1.10.3    Java 17.0.1
    -----------------------------------
    
    lein test tst.demo.jdbc-h2
    
    lein test tst.demo.jdbc-postgres
    
    Ran 7 tests containing 42 assertions.
    0 failures, 0 errors.
    

    See the README for full details.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search