【问题标题】:Dockerized Java app dies with no error message but runs fine standaloneDockerized Java 应用程序死亡,没有错误消息,但独立运行良好
【发布时间】:2018-03-07 17:53:16
【问题描述】:

请注意:知道这个问题与this one 非常相似,但是您会注意到在这种情况下的解决方案是EXPOSE 端口,我已经在做。因此,尽管这个问题听起来相似,但我认为它只是一个完全不同的问题,与另一个问题具有相似的症状


Docker 版本 17.12.0-ce-mac49 (21995) 在这里。我是第一次尝试 Docker,并构建了我的第一个 Docker 映像。我的Dockerfile 是:

FROM openjdk:8

RUN mkdir /opt/myapp

ADD build/libs/myapp.jar /opt/myapp
ADD application.yml /opt/myapp
ADD logback.groovy /opt/myapp
WORKDIR /opt/myapp
EXPOSE 9200
ENTRYPOINT java -Dspring.config=. -jar myapp.jar

我通过以下方式构建它:

docker build -t myapp .

一切顺利。然后我标记它,好像我要将它推送到 Quay:

docker tag <imageId> quay.io/myregistry/myapp:0.1.0-SNAPSHOT

但是,在我发布到 Quay 之前,我想在本地运行它以确保它正常工作:

docker run -it -p 9200:9200 -d --env-file /Users/myuser/myapp-local.env --name myapp myapp

当我运行它时,我得到容器正在运行的指示,我什至可以通过docker ps 看到它几秒钟:

CONTAINER ID        IMAGE               COMMAND                  CREATED                  STATUS              PORTS                    NAMES
f3fa8f7a4288        myapp               "/bin/sh -c 'java -D…"   Less than a second ago   Up 7 seconds        0.0.0.0:9200->9200/tcp   myapp

但是几秒钟后它停止运行并从 docker ps 完全消失:

CONTAINER ID        IMAGE               COMMAND                  CREATED                  STATUS              PORTS                    NAMES

此外,我无法通过 SSH 连接到容器:

docker exec -it f3fa8f7a4288 bash
Error: No such container: f3fa8f7a4288

...或查看任何日志/控制台输出。

当我在 Docker 之外运行 myapp.jar 时(作为典型的 Spring Boot 应用程序,它启动并运行良好,无一例外)。 我该如何排除故障?

【问题讨论】:

  • 你指定你的JVM允许使用多少内存? docker 为运行 jvm 的容器提供了多少 RAM?如果 jvm 使用的内存比它的容器可用的内存多,它就会在没有警告的情况下被杀死。
  • 感谢@luk2302 (+1) 纠正我,如果我错了,但如果你没有指定用于 JVM 的 RAM 量,那么 Java 将允许自己消耗(可能)所有可用的系统内存。由于我可以在 Docker outside 的笔记本电脑上运行它而没有任何问题,我希望 Dockerized JVM 也能做到这一点(除非我的 Docker 配置将容器内存限制到一定大小......)对吧?
  • 您应该能够运行docker logs {container id},即使对于已关闭的容器也是如此。有什么输出?
  • 有点正确,问题是 JVM 错误地确定了内存并且知道您的系统内存,而不是 docker 容器内存 - 假设您的系统有 4gb 内存,您的 docker 容器有 1gb,jvm (即使在 docker 容器中)看到 4gb 并且不担心提前运行 gc。一旦它达到 1gb 的内存,它就会被杀死。 developers.redhat.com/blog/2017/03/14/java-inside-docker
  • 好的,现在我们到了某个地方!有几件事:(1) 我运行了docker logs 并且能够看到它实际上是我的 Spring Boot 应用程序无法连接到本地运行的 MySQL。我将从这里进行故障排除,如果需要,我会发布一个单独的问题,所以谢谢! (2) 因为我的问题的症结是“我该如何排除故障”,如果您想将您的 cmets 转换为使用 docker logs 的推荐,我很乐意给您检查! (3) 另外,尽管 RAM 不是这里的罪魁祸首,但我很好奇如何配置 Docker/JVM RAM,所以这不会让我有朝一日......有什么想法吗?

标签: java docker


【解决方案1】:

docker logs 命令将显示容器在分离运行时生成的输出(使用-d)。这可能包括错误消息。

docker logs --tail 50 --follow --timestamps container

您可以在没有 -d 的情况下在前台运行映像,以查看在 Docker 之外运行 myapp.jar 时的输出。

docker run my/image

所以在这种特殊情况下:

docker run -it -p 9200:9200 --env-file /Users/myuser/myapp-local.env --name myapp myapp

【讨论】:

    【解决方案2】:

    如果我没记错的话,您遇到的问题是因为您使用的是ENTRYPOINTshell 形式。改成使用exec版本,如下:

    ENTRYPOINT ["java", "-Dspring.config=.", "-jar", "myapp.jar"]
    

    shell 表单将像 shell 命令一样将 Java 作为一个单独的进程启动。这会导致 PID 1 返回,使 Docker 相信容器已完成。使用 exec 形式,Java 进程替换 PID 1,容器将继续运行。

    【讨论】:

    • 感谢@Frelling (+1) 这个问题似乎与网络有关(我的应用程序无法与 MySQL 数据库通信),但我很欣赏有关使用 exec 表单的提示!
    猜你喜欢
    • 2017-05-25
    • 2015-12-03
    • 2015-07-12
    • 1970-01-01
    • 2013-11-15
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    相关资源
    最近更新 更多