如何通过 Docker 容器中编译的 jar 使 Clojure Compojure 应用程序 运行 无头?

How to get Clojure Compojure app to run headless via compiled jar within Docker container?

更新:自从最初的一组评论者留下回复后,这个问题已经改变。对任何混淆表示歉意。


这是我的代码存储库https://github.com/Integralist/spurious-clojure-example您可以将它用作我正在使用的示例。

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

我有一个用 Compojure 编写的 "hello world" Clojure 网络应用程序,当 运行 使用 lein ring serverlein run 时我工作正常(因为我有一个 -main 函数现已创建)。它也运行在一定程度上编译成jar和我运行java -jar app.jar

我现在的问题是,如果我尝试从 Docker 容器中 运行 默认值 java -jar app.jar,我会收到以下错误提示...

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:

我的代码当前使用的是 -main 函数,如下所示...

(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))

...但是如何让服务器无头启动?我不能完全按照 Compojure 样板代码来破译它在哪里或如何知道何时 运行 无头或通过浏览器?

我知道您可以在命令行上执行 lein ring server-headless 那么它的程序等效项是什么?

来自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.

因此,如果您在 project.clj 中手动设置环形服务器端口,请确保您也在 Dockerfile 中使用相同的端口,然后在启动时通过 -p 或 -P 提供映射docker.

我不能肯定地说,但我相信你的无头错误消息不会导致你的问题。

因为 ring-server 主要用于开发,它会尝试在服务器启动时打开浏览器。这在没有 GUI 的平台上失败并显示 java.awt.HeadlessException。您需要将 :open-browser? 选项设置为 false 以防止出现这种情况。