You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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运行,保持进程存活。

修复步骤:

  1. 调整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任务配置,避免冲突。
  2. 修改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"]
      
  3. 重新构建并运行:

    • 执行./gradlew bootJar生成可执行JAR
    • 运行docker-compose up --build重新构建容器并启动

额外说明:

无需将Tomcat作为单独容器运行,Spring Boot的内嵌Tomcat完全适配Docker环境。只要打包正确的可执行JAR,就能维持进程持续运行,Tomcat也会正常监听8080端口。

内容的提问来源于stack exchange,提问作者Marat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:07:05