lein ring 服务器在 docker 容器内抛出 java.io.FileNotFoundException

lein ring server throws java.io.FileNotFoundException inside docker container

我正在 docker 中容器化我的 clojure 项目。容器已成功构建,并且上面有 java 1.8.0_151 和 lein 2.8.1 运行ning。但是,当我尝试启动环形服务器时,出现此异常。然而,当我 运行 在 mac 环境中使用相同的代码时,一切正常 运行。

异常:

$ docker-compose up
Starting clojurejournal_clojure_journal_1 ...
Starting clojurejournal_clojure_journal_1 ... done
Attaching to clojurejournal_clojure_journal_1
clojure_journal_1  | --> INFO: starting lein ring server
clojure_journal_1  | Nov 09, 2017 12:16:18 PM com.mchange.v2.log.MLog <clinit>
clojure_journal_1  | INFO: MLog clients using java 1.4+ standard logging.
clojure_journal_1  | 2017-11-09 12:16:20.027:INFO:oejs.Server:jetty-7.6.1.v20120215
clojure_journal_1  | 2017-11-09 12:16:20.084:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:3000
clojure_journal_1  | Started server on port 3000
clojure_journal_1  | Exception in thread "main" java.io.FileNotFoundException: http://localhost:3000, compiling:(/tmp/form-init462348242831821276.clj:1:71)
clojure_journal_1  |    at clojure.lang.Compiler.load(Compiler.java:7142)
clojure_journal_1  |    at clojure.lang.Compiler.loadFile(Compiler.java:7086)
clojure_journal_1  |    at clojure.main$load_script.invoke(main.clj:274)
clojure_journal_1  |    at clojure.main$init_opt.invoke(main.clj:279)
clojure_journal_1  |    at clojure.main$initialize.invoke(main.clj:307)
clojure_journal_1  |    at clojure.main$null_opt.invoke(main.clj:342)
clojure_journal_1  |    at clojure.main$main.doInvoke(main.clj:420)
clojure_journal_1  |    at clojure.lang.RestFn.invoke(RestFn.java:421)
clojure_journal_1  |    at clojure.lang.Var.invoke(Var.java:383)
clojure_journal_1  |    at clojure.lang.AFn.applyToHelper(AFn.java:156)
clojure_journal_1  |    at clojure.lang.Var.applyTo(Var.java:700)
clojure_journal_1  |    at clojure.main.main(main.java:37)
clojure_journal_1  | Caused by: java.io.FileNotFoundException: http://localhost:3000
clojure_journal_1  |    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
clojure_journal_1  |    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
clojure_journal_1  |    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
clojure_journal_1  |    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.run(HttpURLConnection.java:1944)
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.run(HttpURLConnection.java:1939)
clojure_journal_1  |    at java.security.AccessController.doPrivileged(Native Method)
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1938)
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1508)
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
clojure_journal_1  |    at javax.swing.JEditorPane.getStream(JEditorPane.java:768)
clojure_journal_1  |    at javax.swing.JEditorPane.setPage(JEditorPane.java:432)
clojure_journal_1  |    at javax.swing.JEditorPane.setPage(JEditorPane.java:880)
clojure_journal_1  |    at javax.swing.JEditorPane.<init>(JEditorPane.java:274)
clojure_journal_1  |    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
clojure_journal_1  |    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
clojure_journal_1  |    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
clojure_journal_1  |    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
clojure_journal_1  |    at clojure.lang.Reflector.invokeConstructor(Reflector.java:180)
clojure_journal_1  |    at clojure.java.browse_ui$open_url_in_swing.invoke(browse_ui.clj:15)
clojure_journal_1  |    at clojure.lang.Var.invoke(Var.java:379)
clojure_journal_1  |    at clojure.java.browse$open_url_in_swing.invoke(browse.clj:64)
clojure_journal_1  |    at clojure.java.browse$browse_url.invoke(browse.clj:76)
clojure_journal_1  |    at ring.server.standalone$open_browser_to.invoke(standalone.clj:39)
clojure_journal_1  |    at ring.server.standalone$serve$fn__1676.invoke(standalone.clj:102)
clojure_journal_1  |    at ring.server.standalone$try_port.invoke(standalone.clj:16)
clojure_journal_1  |    at ring.server.standalone$serve.doInvoke(standalone.clj:95)
clojure_journal_1  |    at clojure.lang.RestFn.invoke(RestFn.java:423)
clojure_journal_1  |    at ring.server.leiningen$serve.invoke(leiningen.clj:20)
clojure_journal_1  |    at user$eval3389.invoke(form-init462348242831821276.clj:1)
clojure_journal_1  |    at clojure.lang.Compiler.eval(Compiler.java:6703)
clojure_journal_1  |    at clojure.lang.Compiler.eval(Compiler.java:6693)
clojure_journal_1  |    at clojure.lang.Compiler.load(Compiler.java:7130)
clojure_journal_1  |    ... 11 more
clojure_journal_1  | Caused by: java.io.FileNotFoundException: http://localhost:3000
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1890)
clojure_journal_1  |    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
clojure_journal_1  |    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
clojure_journal_1  |    at javax.swing.JEditorPane.getStream(JEditorPane.java:733)
clojure_journal_1  |    ... 33 more

docker文件:

FROM ubuntu:xenial

LABEL maintainer=freid
ENV WORK_DIR /var/www

# install dependancies
RUN apt-get update
RUN apt-get install -y default-jre curl wget

RUN wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
RUN chmod +x lein
RUN mv lein /usr/local/bin

# copy to /var/www
COPY . $WORK_DIR

# make it a working directory
WORKDIR $WORK_DIR

# fix permissions
RUN chmod a+x /var/www/entrypoint.sh

# expose port 3000
EXPOSE 3000

# make entrypoint
ENTRYPOINT ["/bin/sh", "/var/www/entrypoint.sh"]

docker-撰写:

clojure_journal:
  image: clojure_journal:latest
  command: run
  ports:
    - 3000:3000
  volumes:
    - .:/opt/clojure_journal

entrypoint.sh

#!/usr/bin/env bash

start(){
    echo "--> INFO: starting lein ring server"
    lein ring server
}

case  in

run)
    shift 1
    start $@
;;

*)
   >&2 echo "---> INFO: running: ''."
;;
esac

根据@Taylor Wood 的评论,使用 lein ring server-headless 解决了问题。

查看异常堆栈跟踪,您的代码似乎在启动期间试图打开浏览器 http://localhost:3000,这可能不是您希望从容器中获得的结果。我假设您只想 运行 来自容器的 HTTP 服务器。在您的 entrypoint.sh 脚本中尝试 lein ring server-headless,这将阻止它尝试打开浏览器

顺便说一句,假设您是不使用 Docker 图像作为开发环境。这样你就不需要安装 Leiningen,这意味着你可以只使用 OpenJDK image 而你的 Docker 文件会简单得多:

FROM java:8-alpine    
ADD path/to/your.jar /your-app/app.jar
EXPOSE 3000 
CMD ["java", "-jar", "/your-app/app.jar"]