我有一个用
java
编写的服务器端项目,包括 maven
和 spring-boot
我正在尝试在 Docker 中运行它。
我在 VSCODE 中编写整个程序并为其创建一个特殊的 Dockerfile。
然后我希望能够从我的项目创建一个 jar,当我构建图像并在容器中运行它时,我可以看到服务器端。
这是我的 Dockerfile:
FROM maven:3.8.1-openjdk-11 AS build
WORKDIR /usr/src/app
COPY pom.xml .
COPY src ./src
RUN mvn package
ENTRYPOINT ["java","-jar","target/my-app-1.0.0.jar"]
这是我的 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>src</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<properties>
<start-class>src.MyApplication</start-class>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>src.MyApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
MyApplication.java:
package src;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
我的文件夹结构是这样的:
.
├── src
| └──controllers
| │ └──controller.java
| └──models
| │ └──classA.java
| | └──classB.java
| └──services
| | └──service.java
| └──MyApplication.java
├── Dockerfile
├── pom.xml
当我运行
docker build -t app
命令时。看起来没有问题,构建成功,但是当我稍后运行命令docker run -p 8080:8080 app
时,出现此错误
Error: Could not find or load main class src.MyApplication Caused by: java.lang.ClassNotFoundException: src.MyApplication
有人可以为我提供解决方案吗?
src
这个词在很多方面都令人困惑。
按照惯例,源代码保存在名为
src/main
的文件夹中,然后您通常会在该文件夹下为您的组织名称和应用程序创建文件夹。
因此,假设您是 ACME Corporation,拥有一个域名 acme.com,并且您的应用程序与鱼有关,那么您可以将所有代码打包在包名称
com.acme.fish
下(域名反转,然后是应用程序名称,等等)。
在java中,类需要位于与类名匹配的文件中,并且按照惯例,这些文件应该具有首字母大写。所以
ClassA.java
不是classA.java
。
这将是一个更传统的结构:
├── Dockerfile
├── pom.xml
└── src
└── main
└── com
└── acme
└── fish
├── MyApplication.java
├── controllers
│ └── Controller.java
├── models
│ ├── ClassA.java
│ └── ClassB.java
└── services
└── Service.java
那么在你的
pom.xml
<mainClass>
中将是:
<mainClass>com.acme.fish.MyApplication</mainClass>
从这样的重组开始。
如果这仍然不起作用,请使用解压缩工具并查看 zip 文件的结构。在
classses
文件夹中,您最终应该会看到 com/acme/fish/MyApplication.class
有几点是错误的。
src/main/java
spring-context
依赖项和 spring-boot-autoconfigure
依赖项,已通过启动程序包含在内。spring-boot-maven-plugin
不maven-jar-plugin
。已更正
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>src</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
</parent>
<properties>
<java.version>17</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
将您的类移至类似
io.maia
之类的基础包,并使用 src/main/java
获得正确的 Maven 结构。
Spring Boot 3.x 需要 Java 17 或更高版本,因此也请更新您的
Dockerfile
。您可能还想利用多阶段构建(1 个阶段用于构建,1 个阶段用于实际运行)。
FROM maven:3.8-openjdk-17 AS build
WORKDIR /usr/src/app
COPY pom.xml .
COPY src ./src
RUN mvn package
FROM openjdk:21-slim
copy --from=build target/my-app-1.0.0.jar my-app-1.0.0.jar
ENTRYPOINT ["java","-jar","my-app-1.0.0.jar"]
或者,如果您的唯一目标是在容器中运行应用程序,请放弃
Dockerfile
并运行 mvn spring-boot:build-image
来获取可运行且优化的图像。