Docker中Spring Boot Web应用内嵌Tomcat无法启动且容器退出码为0求助
问题:Docker中Spring Boot Web应用启动后立即退出(状态码0),内嵌Tomcat未持续运行
问题描述
在Docker容器中运行搭载PostgreSQL的Spring Boot Web应用时,内嵌Tomcat服务器未能持续运行,容器以状态码0退出,表明主进程(Spring Boot应用)启动完成后立即终止。
已执行的排查步骤
- 检查Spring Boot应用日志,未发现Tomcat启动失败的错误或异常
- 使用
docker logs命令查看容器日志,仅看到应用启动后立刻触发关闭流程 - 检查Dockerfile和Docker Compose配置,确认依赖、入口点等配置无明显错误
- 验证PostgreSQL数据库连接配置,确认URL、凭据和驱动类正确,且应用能正常连接数据库
- 尝试添加健康检查,未解决容器提前关闭问题
相关配置文件
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.2.0' id 'io.spring.dependency-management' version '1.1.4' } bootJar{ duplicatesStrategy = DuplicatesStrategy.EXCLUDE } apply plugin: 'java' springBoot { mainClass = 'com.example.fcs.FeedbackCollectionSystemApplication' buildInfo() } jar { manifest { attributes 'Main-Class': 'com.example.fcs.FeedbackCollectionSystemApplication' } archiveFileName = 'app.jar' destinationDirectory.set(file('src/main/docker')) from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } duplicatesStrategy = DuplicatesStrategy.EXCLUDE } group = 'com.example' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-tomcat' implementation 'org.postgresql:postgresql' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
docker-compose.yml
version: '3.8' services: postgres: image: postgres:13-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: 11111111Aa POSTGRES_DB: feedback ports: - "5432:5432" volumes: - postgres-data:/var/lib/postgresql/data app: build: . ports: - "8080:8080" depends_on: - postgres environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/feedback SPRING_DATASOURCE_USERNAME: postgres SPRING_DATASOURCE_PASSWORD: 11111111Aa volumes: postgres-data:
Dockerfile
FROM openjdk:19 VOLUME /tmp EXPOSE 8080 ARG JAR_FILE=/*.jar ADD ${JAR_FILE} app.jar CMD ["java","-jar","/app.jar"] #or entrypoint idk
主类代码
package com.example.fcs; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class FeedbackCollectionSystemApplication { public static void main(String[] args) { SpringApplication.run(FeedbackCollectionSystemApplication.class, args); } }
容器日志
app-1 | :: Spring Boot :: (v3.2.0) app-1 | app-1 | 16:48:21.928 [main] INFO com.example.fcs.FeedbackCollectionSystemApplication -- Starting FeedbackCollectionSystemApplication using Java 19 with PID 1 (/app.jar started by root in /) app-1 | 16:48:21.941 [main] INFO com.example.fcs.FeedbackCollectionSystemApplication -- No active profile set, falling back to 1 default profile: "default" app-1 | 16:48:22.942 [main] INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate -- Bootstrapping Spring Data JPA repositories in DEFAULT mode. app-1 | 16:48:23.022 [main] INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate -- Finished Spring Data repository scanning in 70 ms. Found 2 JPA repository interfaces. app-1 | 16:48:23.484 [main] INFO com.zaxxer.hikari.HikariDataSource -- HikariPool-1 - Starting... app-1 | 16:48:23.722 [main] INFO com.zaxxer.hikari.pool.HikariPool -- HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@4a34e9f app-1 | 16:48:23.724 [main] INFO com.zaxxer.hikari.HikariDataSource -- HikariPool-1 - Start completed. app-1 | 16:48:23.778 [main] INFO org.hibernate.jpa.internal.util.LogHelper -- HHH000204: Processing PersistenceUnitInfo [name: default] app-1 | 16:48:23.851 [main] INFO org.hibernate.Version -- HHH000412: Hibernate ORM core version [WORKING] app-1 | 16:48:23.900 [main] INFO org.hibernate.cache.internal.RegionFactoryInitiator -- HHH000026: Second-level cache disabled app-1 | 16:48:24.136 [main] INFO org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo -- No LoadTimeWeaver setup: ignoring JPA class transformer app-1 | 16:48:25.238 [main] INFO org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator -- HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) app-1 | 16:48:25.243 [main] INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean -- Initialized JPA EntityManagerFactory for persistence unit 'default' app-1 | 16:48:25.918 [main] INFO com.example.fcs.FeedbackCollectionSystemApplication -- Started FeedbackCollectionSystemApplication in 4.361 seconds (process running for 4.706) app-1 | 16:48:25.926 [SpringApplicationShutdownHook] INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean -- Closing JPA EntityManagerFactory for persistence unit 'default' app-1 | 16:48:25.930 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource -- HikariPool-1 - Shutdown initiated... app-1 | 16:48:25.936 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource -- HikariPool-1 - Shutdown completed. app-1 exited with code 0
解决方案
从日志可以看出,Spring Boot应用启动完成后立刻触发了关闭流程,核心原因是当前打包的是普通JAR文件,而非Spring Boot可执行JAR。普通JAR仅执行main方法初始化Spring上下文,不会启动内嵌Tomcat并保持进程运行;而Spring Boot可执行JAR会通过启动器维持Tomcat运行,保持进程存活。
修复步骤:
调整build.gradle配置:
- 移除或禁用普通
jar任务,优先使用Spring Boot提供的bootJar任务。bootJar默认生成可执行JAR,包含所有依赖和Tomcat启动逻辑。 - 修改
bootJar任务,指定输出目录和文件名,确保Docker能正确获取到可执行JAR:bootJar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE archiveFileName = 'app.jar' destinationDirectory.set(file('build/libs')) } - 删除原有的
jar任务配置,避免冲突。
- 移除或禁用普通
修改Dockerfile:
- 更新
JAR_FILE参数,指向bootJar生成的文件路径:FROM openjdk:19 VOLUME /tmp EXPOSE 8080 ARG JAR_FILE=build/libs/app.jar ADD ${JAR_FILE} app.jar CMD ["java","-jar","/app.jar"]
- 更新
重新构建并运行:
- 执行
./gradlew bootJar生成可执行JAR - 运行
docker-compose up --build重新构建容器并启动
- 执行
额外说明:
无需将Tomcat作为单独容器运行,Spring Boot的内嵌Tomcat完全适配Docker环境。只要打包正确的可执行JAR,就能维持进程持续运行,Tomcat也会正常监听8080端口。
内容的提问来源于stack exchange,提问作者Marat
相关产品推荐
相关产品推荐

