0

Update: this question has changed since the original set of commenters left responses. Apologies for any confusion.


This is my code repository https://github.com/Integralist/spurious-clojure-example you can use it as an example for what I'm working with.

Note that the above repo relies on a library I've not yet published to Clojars (as I'm still testing it - hence this question opened). You can see the source code of the library here: https://github.com/Integralist/spurious-clojure-aws-sdk-helper

I have a "hello world" Clojure web app written with Compojure that I have working fine when run using lein ring server and lein run (as I have a -main function now created). It also runs to a certain extent when compiled down into a jar and I run java -jar app.jar.

My problem now is that if I try to run the default java -jar app.jar from within a Docker container I get the following error telling me...

spurious-clojure-example is starting
2015-02-14 00:58:03.812:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
2015-02-14 00:58:03.854:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080
Started server on port 8080
Exception in thread "main" java.awt.HeadlessException:

My code is currently using a -main function like so...

(ns spurious-clojure-example.repl
  (:use spurious-clojure-example.handler
        ring.server.standalone
        [ring.middleware file-info file])
  (:gen-class))

(defonce server (atom nil))

(defn get-handler []
  (-> #'app
    (wrap-file "resources")
    (wrap-file-info)))

(defn start-server
  "used for starting the server in development mode from REPL"
  [& [port]]
  (let [port (if port (Integer/parseInt port) 8080)]
    (reset! server
            (serve (get-handler)
                   {:port port
                    :init init
                    :auto-reload? true
                    :destroy destroy
                    :join true}))
    (println (str "You can view the site at http://localhost:" port))))

(defn stop-server []
  (.stop @server)
  (reset! server nil))

(defn -main []
  (start-server))

...but how do I get the server to start headless? I can't quite follow the Compojure boilerplate code to decipher where or how it knows when to run headlessly or via browser?

I know that on the command line you can do lein ring server-headless so what's the programmatic equivalent of that?

Integralist
  • 5,899
  • 5
  • 25
  • 42
  • Please add the contents of your `project.clj`. Especially the section for `:ring` and profiles are of interest. – schaueho Feb 20 '15 at 14:04
  • @schaueho here is the `project.clj` https://github.com/Integralist/spurious-clojure-example/blob/master/project.clj (also inlined above) – Integralist Feb 20 '15 at 14:31
  • A side note, but IMO it would be better to use 2 containers. One to build the application and another one to host it. In the hosting container you just have the JRE and the uber jar. – Adrian Mouat Feb 20 '15 at 20:32

2 Answers2

2

Because ring-server is primarily meant for development, it tries to open a browser when the server starts. This fails with a java.awt.HeadlessException on platforms without a GUI. You'll want to set the :open-browser? option to false to prevent this.

weavejester
  • 575
  • 3
  • 3
0

From the offical Docker docs on EXPOSE

The EXPOSE instructions informs Docker that the container will listen on the specified network ports at runtime. Docker uses this information to interconnect containers using links (see the Docker User Guide) and to determine which ports to expose to the host when using the -P flag. Note: EXPOSE doesn't define which ports can be exposed to the host or make ports accessible from the host by default. To expose ports to the host, at runtime, use the -p flag or the -P flag.

So if you're setting the ring server port manually in your project.clj, ensure that you're using the same port also in your Dockerfile and then provide a mapping via -p or -P when starting docker.

I can't say for sure but I believe that your headless error message doesn't contribute to your problem.

schaueho
  • 3,419
  • 1
  • 21
  • 32
  • OK, so it seems I just needed to add the `-p` flag as suggested rather than have the name in my Dockerfile. I was then able to access the compojure page in my browser. So I'm going to update my question to reflect that and so it leaves the main question being effectively: "how to package a clojure compojure app so that when the jar is run it doesn't drop you into a repl" – Integralist Feb 20 '15 at 17:02