【问题标题】:How can I serve a multi-module spring boot application in a single Docker Container?如何在单个 Docker 容器中提供多模块 Spring Boot 应用程序?
【发布时间】:2021-04-03 09:54:55
【问题描述】:

我有一个类似于这个项目结构的多模块 spring boot 应用程序:

hello-world
│   
├── hello-world-core
│   └── HelloWorldApplication.java
│   └── pom.xml <--- hello-world-core POM
│   └── src     <--- hello-world-core src
│   └── target  <--- hello-world-core target with jar
├── hello-world-users
│   └── pom.xml <--- hello-world-users POM
│   └── src     <--- hello-world-users src
│   └── target  <--- hello-world-users target with jar
├── hello-world-website
│   └── pom.xml <--- hello-world-website POM
│   └── src     <--- hello-world-website src
│   └── target  <--- hello-world-website target with jar
└── pom.xml

现在我想在单个 Docker 容器中使用像这样的图像为应用程序提供服务:

# jdk 11 image
FROM maven:3.6-jdk-11 as builder

# Copy local code to the container image.
WORKDIR /app

# copy the project files
COPY pom.xml .

# copy your other files
COPY src ./src

# Build a release artifact.
RUN mvn package -DskipTests

# Use AdoptOpenJDK for base image.
FROM adoptopenjdk/openjdk11:alpine-slim

# Copy the jar to the production image from the builder stage.
COPY --from=builder /app/target/hello-world*.jar /hello-world.jar

EXPOSE 8080

# Run the web service on container startup.
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/hello-world.jar"]

为了使用这个 Dockerfile 来提供它,我需要从这个项目中创建一个 single jar

现在我想知道:

  1. 有没有更好的方法在单个 Docker 容器中提供此类应用程序(不使用 docker-compose)?
  2. 如何使用 maven 从这个结构中创建一个 jar?

【问题讨论】:

  • 容器的理念是每个容器有一个应用程序。常见的模式是使用 Docker Compose (docs.docker.com/compose) 之类的东西在一台主机上运行多个 Docker 镜像并设置它们之间的通信路由。
  • 感谢您的快速回复!通常我使用 docker compose 来提供模块,但在这种情况下,我尝试只创建一个容器。有没有好的解决方案?
  • 首先你有一个spring boot应用程序,这意味着你有一个包含整个应用程序的jar文件。另一个问题是:为什么要在 docker 内部构建而不是在外部构建,因为您没有在容器内映射缓存卷,这会导致重复下载依赖项。除此之外,为什么要在不运行测试的情况下进行构建?我建议在 docker 容器之外构建您的应用程序,只需将生成的 jar 文件复制到容器中即可。 github.com/GoogleContainerTools/jib/tree/master/examples/… 也可能有帮助

标签: java spring-boot docker maven dockerfile


【解决方案1】:

如果您想在一个容器中执行此操作,有一些方法可以做到这一点,

  1. 您可以像已经拥有的那样分别构建 3 个不同的 spring 模块,并在同一映像的不同端口中运行这 3 个 jar。因此,为此您必须使用 maven 更改绑定在 jar 中的端口,因为我们试图在 1 个容器中运行所有 3 个进程,因此如果您尝试这样做,使用 8080(默认)将导致错误。

server.port=9090

application.properties 中的类似内容会有所帮助。 因此,之后您必须在容器内手动运行它们或将它们全部附加到容器启动脚本中。

例如:

RUN java -jar hello-world-core.jar & java -jar hello-world-users.jar

因此,当您执行此操作时,不同的 jar 将在您在 pom 文件中分别提到的不同端口上提供服务。因此,为了从外部访问它们,您还必须公开这些端口。

  1. 如果您真的希望将它们放在一个容器中,为什么一开始就将它们分开?并在它们上面执行 3 个单独的 tomcat 吗?我的意思是所有 3 个应用程序内部都有单独的 tomcat,这就是我们努力将其合并为 1 的原因。那么为什么我们不逃避这些 tomcat 并构建 war 文件,然后在容器中安装一个 tomcat 并将所有战争放入 webapps 文件夹?这意味着您必须将一个 tomcat 放到 docker 上并使用它,以便所有应用程序都使用同一个 tomcat 并且可以通过 8080 访问。

  2. 我相信从微服务的角度来看,将它们分开是很好的,是的,这样做有利也有弊。我也同意@khmarbaise 在他的评论中提出的观点,跳过测试不是一个好主意。 :D

【讨论】:

    猜你喜欢
    • 2019-02-06
    • 2018-07-11
    • 2019-12-10
    • 2017-02-21
    • 2022-09-23
    • 2017-07-04
    • 2021-11-26
    • 2015-05-24
    • 1970-01-01
    相关资源
    最近更新 更多