1. 项目背景与核心价值
SpringBoot应用默认以JAR包形式运行,但企业级部署常需WAR包部署到传统Tomcat服务器。Docker化部署则进一步解决了环境一致性、资源隔离和快速伸缩问题。将SpringBoot WAR包部署到Docker中的Tomcat容器,本质上是在云原生环境下复现经典JavaEE部署模式。
这种混合部署方案的价值在于:
- 保留SpringBoot开发效率的同时满足企业现有运维体系
- 利用Docker实现环境标准化和快速部署
- 兼容需要共享Tomcat资源的历史遗留系统
- 为单体应用向微服务架构过渡提供缓冲层
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 开发环境要求
- JDK 1.8+(推荐Amazon Corretto 11)
- Maven 3.6+(需配置阿里云镜像加速)
- Docker Desktop 4.12+(Windows/Mac)或 Docker CE 20.10+(Linux)
- IDE支持(IntelliJ IDEA或Eclipse STS)
注意:Windows环境需确保WSL2已启用,Docker分配内存建议≥4GB
2.2 SpringBoot项目改造
在pom.xml中需进行以下关键修改:
xml复制<!-- 修改打包方式 -->
<packaging>war</packaging>
<!-- 移除内置Tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
2.3 初始化类改造
需继承SpringBootServletInitializer:
java复制public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(YourApplication.class);
}
}
3. Docker化部署全流程
3.1 构建WAR包
执行Maven打包命令:
bash复制mvn clean package -DskipTests
生成的WAR包默认位于target目录,命名格式为${artifactId}-${version}.war
3.2 准备Docker环境
3.2.1 拉取官方Tomcat镜像
bash复制docker pull tomcat:9.0-jdk11
建议选择与本地JDK版本匹配的镜像,避免兼容性问题
3.2.2 自定义Dockerfile
dockerfile复制FROM tomcat:9.0-jdk11
LABEL maintainer="your.email@example.com"
# 删除默认ROOT应用
RUN rm -rf /usr/local/tomcat/webapps/ROOT
# 复制WAR包到容器
COPY target/your-app-0.0.1.war /usr/local/tomcat/webapps/ROOT.war
# 暴露端口
EXPOSE 8080
# 启动命令
CMD ["catalina.sh", "run"]
关键参数说明:
webapps/ROOT.war部署为根路径应用- 使用
catalina.sh run保持前台运行 - 时区问题可通过
-e TZ=Asia/Shanghai解决
3.3 构建与运行容器
bash复制# 构建镜像
docker build -t your-app-image .
# 运行容器
docker run -d \
--name your-app \
-p 8080:8080 \
-v /path/to/logs:/usr/local/tomcat/logs \
your-app-image
4. 高级配置与优化
4.1 性能调优参数
在Docker运行时可添加JVM参数:
bash复制docker run -d \
-e JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC" \
# 其他参数...
4.2 多阶段构建优化
改进后的Dockerfile:
dockerfile复制# 构建阶段
FROM maven:3.8-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段
FROM tomcat:9.0-jdk11
COPY --from=builder /app/target/*.war /usr/local/tomcat/webapps/ROOT.war
4.3 健康检查配置
dockerfile复制HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
5. 常见问题排查指南
5.1 应用无法访问
检查步骤:
- 确认容器状态:
docker ps -a - 查看容器日志:
docker logs your-app - 检查端口映射:
docker port your-app - 进入容器调试:
docker exec -it your-app bash
5.2 静态资源404
解决方案:
- 确保资源位于
src/main/webapp目录 - 检查Spring资源映射配置:
java复制@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("classpath:/static/"); }
5.3 数据库连接失败
容器内需使用宿主IP或服务名:
properties复制spring.datasource.url=jdbc:mysql://host.docker.internal:3306/db
6. 生产环境建议
- 使用Docker Compose编排数据库等依赖服务
- 配置日志轮转和持久化存储
- 设置合理的资源限制:
bash复制docker run -d \ --memory=1g \ --cpus=1 \ # 其他参数... - 考虑使用Tomcat连接池优化参数:
properties复制server.tomcat.max-connections=200 server.tomcat.max-threads=100
7. 部署流程自动化
7.1 CI/CD集成示例
.gitlab-ci.yml配置片段:
yaml复制stages:
- build
- deploy
build:
stage: build
image: maven:3.8-openjdk-11
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.war
deploy:
stage: deploy
image: docker:20.10
services:
- docker:dind
script:
- docker build -t your-registry/your-app .
- docker push your-registry/your-app
- ssh user@server "docker pull your-registry/your-app && docker-compose up -d"
7.2 版本管理策略
推荐镜像标签方案:
- 开发环境:
latest - 测试环境:
{version}-SNAPSHOT - 生产环境:
{version}
通过环境变量注入配置:
bash复制docker run -d \
-e SPRING_PROFILES_ACTIVE=prod \
# 其他参数...
8. 监控与维护
8.1 基础监控配置
Prometheus监控示例:
yaml复制# application.yml
management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
tags:
application: ${spring.application.name}
8.2 日志收集方案
ELK栈集成建议:
- 配置Logback输出JSON格式日志
- Filebeat收集容器日志
- 使用Docker日志驱动:
bash复制docker run --log-driver=syslog \ --log-opt syslog-address=tcp://logserver:514 \ # 其他参数...
9. 安全加固措施
- 使用非root用户运行:
dockerfile复制RUN useradd -m tomcat_user && \ chown -R tomcat_user:tomcat_user /usr/local/tomcat USER tomcat_user - 定期更新基础镜像
- 配置Tomcat安全策略:
bash复制docker run -d \ -e CATALINA_OPTS="-Dsecurerandom.source=file:/dev/urandom" \ # 其他参数...
10. 替代方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 传统WAR部署 | 运维熟悉度高 | 环境依赖强 |
| Docker化JAR | 部署简单 | 不兼容传统中间件 |
| 本文方案 | 兼顾传统与云原生 | 配置复杂度略高 |
| Kubernetes部署 | 扩展性强 | 学习曲线陡峭 |
实际项目中,我曾遇到需要同时对接老式ERP系统和新建微服务的场景。这种混合部署方案允许我们在保持历史系统稳定的同时,逐步将新功能迁移到云原生架构。关键是要在pom.xml中精确控制依赖范围,避免因传递依赖导致类冲突。
