Docker + Nginx 部署 Java 项目(JAR 包 + WAR 包)实战笔记
一、核心场景与环境准备
1. 部署目标
通过 Docker 容器化 Nginx 作为反向代理服务器,转发请求到 Java 项目(SpringBoot JAR 包 或 传统 WAR 包),实现“静态资源代理 + 接口转发 + 端口统一管理”,适配开发/生产环境部署。
2. 前置环境
- 本地/服务器安装 Docker(Docker Desktop 或 Linux 版 Docker)、Docker Compose(Docker Desktop 自带,Linux 需单独安装);
- Java 项目已打包完成(JAR 包 或 WAR 包);
- 了解基础 Docker 命令(镜像构建、容器启停)和 Nginx 反向代理配置。
3. 核心架构
用户请求 → Nginx(80/443 端口)→ 反向代理 → Java 项目容器(8080/8081 端口)
- Nginx 作用:统一入口端口、处理静态资源、转发接口请求、配置 HTTPS;
- Java 容器:独立运行 JAR/WAR 包,与 Nginx 通过 Docker 网络通信。
二、部署 SpringBoot JAR 包(推荐,内置 Tomcat)
1. 项目准备
- 本地 SpringBoot 项目打包为可执行 JAR 包(如
dramamini.jar),确保打包命令正确:mvn clean package -Dmaven.test.skip=true - 打包后在
target/目录获取 JAR 包,复制到部署目录(如docker-java-demo/)。
2. 部署目录结构
docker-java-demo/
├── java/ # Java 项目目录
│ └── dramamini.jar # SpringBoot JAR 包
├── nginx/ # Nginx 配置目录
│ ├── nginx.conf # Nginx 核心配置
│ └── html/ # 静态资源(可选,如前端页面)
└── docker-compose.yml # 多容器管理配置
3. 关键配置文件
(1)Nginx 配置(nginx/nginx.conf)
核心实现“接口反向代理”,转发请求到 Java 容器:
worker_processes 1;
events { worker_connections 1024; }http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" "$http_user_agent"';access_log /var/log/nginx/access.log main;sendfile on;keepalive_timeout 65;# 反向代理 Java 项目server {listen 80;server_name localhost;# 静态资源代理(如前端页面,可选)location / {root /usr/share/nginx/html;index index.html;}# 接口请求转发到 Java 容器(/api 前缀可自定义)location /api/ {proxy_pass http://java-app:8080/; # java-app 是 Docker 容器名,8080 是 Java 项目端口proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}}
}
(2)Docker Compose 配置(docker-compose.yml)
统一管理 Nginx 和 Java 容器,确保网络互通:
version: '3.8'
services:# Nginx 容器(反向代理)nginx:image: nginx:alpinecontainer_name: nginx-proxyports:- "80:80" # 宿主机 80 端口映射到 Nginx 80 端口volumes:- ./nginx/nginx.conf:/etc/nginx/nginx.conf # 挂载 Nginx 配置- ./nginx/html:/usr/share/nginx/html # 挂载静态资源- ./nginx/logs:/var/log/nginx # 挂载日志(可选)restart: alwaysnetworks:- java-networkdepends_on:- java-app # 确保 Java 容器先启动# Java 项目容器(JAR 包)java-app:image: openjdk:8-jdk-alpine # 基础 Java 镜像(匹配项目 JDK 版本)container_name: java-appvolumes:- ./java/dramamini.jar:/app/dramamini.jar # 挂载 JAR 包- ./java/logs:/app/logs # 挂载 Java 日志(可选)working_dir: /appcommand: java -jar dramamini.jar --spring.profiles.active=test # 启动命令(可加 JVM 参数)restart: alwaysnetworks:- java-networkexpose:- "8080" # 暴露容器内端口(无需映射到宿主机,Nginx 内部访问)networks:java-network:driver: bridge # 自定义桥接网络,确保容器互通
4. 部署步骤
(1)启动容器
进入 docker-java-demo/ 目录,执行:
# 后台启动所有容器
docker compose up -d
# 查看容器状态(确保 both 状态为 Up)
docker compose ps
(2)验证部署
- 访问静态资源(若有):
http://localhost→ 显示 Nginx 挂载的静态页面; - 访问 Java 接口:
http://localhost/api/xxx→ Nginx 转发到 Java 容器,返回接口响应; - 查看日志(排查问题):
# 查看 Nginx 日志 docker compose logs -f nginx # 查看 Java 项目日志 docker compose logs -f java-app
(3)更新项目(如 JAR 包迭代)
# 1. 替换 ./java/ 目录下的旧 JAR 包为新包
# 2. 重启 Java 容器(无需重启 Nginx)
docker compose restart java-app
三、部署传统 WAR 包(需外部 Tomcat)
1. 项目准备
- 传统 Java Web 项目(如 SSM)打包为 WAR 包(如
demo.war); - 确保 WAR 包兼容 Tomcat 版本(推荐 Tomcat 8.5/9.0)。
2. 部署目录结构
docker-war-demo/
├── tomcat/ # Tomcat 相关目录
│ ├── webapps/ # WAR 包存放目录
│ │ └── demo.war # Java WAR 包
│ └── conf/ # Tomcat 配置(可选,如需修改端口)
├── nginx/ # 同 JAR 包部署的 Nginx 目录(复用配置)
│ ├── nginx.conf
│ └── html/
└── docker-compose.yml
3. 关键配置文件
(1)Nginx 配置(复用 JAR 包部署的 nginx.conf)
无需修改,核心转发逻辑一致(proxy_pass http://tomcat-app:8080/)。
(2)Docker Compose 配置(docker-compose.yml)
替换 Java 容器为 Tomcat 容器,挂载 WAR 包到 Tomcat 的 webapps/ 目录:
version: '3.8'
services:nginx:# 同 JAR 包部署的 Nginx 配置,无需修改image: nginx:alpinecontainer_name: nginx-proxyports:- "80:80"volumes:- ./nginx/nginx.conf:/etc/nginx/nginx.conf- ./nginx/html:/usr/share/nginx/htmlrestart: alwaysnetworks:- java-networkdepends_on:- tomcat-app# Tomcat 容器(运行 WAR 包)tomcat-app:image: tomcat:8.5-alpine # 选择对应版本的 Tomcat 镜像container_name: tomcat-appvolumes:- ./tomcat/webapps:/usr/local/tomcat/webapps # 挂载 WAR 包到 Tomcat- ./tomcat/logs:/usr/local/tomcat/logs # 挂载 Tomcat 日志(可选)# 如需修改 Tomcat 端口,挂载 server.xml(可选)# - ./tomcat/conf/server.xml:/usr/local/tomcat/conf/server.xmlrestart: alwaysnetworks:- java-networkexpose:- "8080" # Tomcat 默认端口networks:java-network:driver: bridge
4. 部署步骤
(1)启动容器
cd docker-war-demo/
docker compose up -d
- Tomcat 会自动解压
webapps/下的 WAR 包(如demo.war→demo/目录); - 访问路径:若 WAR 包名为
demo.war,则接口路径为http://localhost/api/demo/xxx(需同步修改 Nginx 配置中的proxy_pass为http://tomcat-app:8080/demo/)。
(2)验证部署
- 访问接口:
http://localhost/api/xxx→ Nginx 转发到 Tomcat 容器,返回 WAR 包接口响应; - 查看 Tomcat 日志(确认 WAR 包部署成功):
docker compose logs -f tomcat-app
(3)更新 WAR 包
# 1. 替换 ./tomcat/webapps/ 下的旧 WAR 包为新包
# 2. 重启 Tomcat 容器(Tomcat 自动重新解压 WAR 包)
docker compose restart tomcat-app
四、生产环境优化(可选)
1. HTTPS 配置(Nginx 层面)
- 生成 Let’s Encrypt 免费证书(生产环境)或自签名证书(测试);
- 修改 Nginx 配置,添加 443 端口监听和证书挂载(参考前文 HTTPS 配置);
- 在
docker-compose.yml中给 Nginx 新增 443 端口映射:- "443:443"。
2. 容器优化
- Java 容器添加 JVM 参数(如限制内存):
# JAR 包容器 command 示例 command: java -Xms512m -Xmx1024m -jar dramamini.jar - Tomcat 容器修改连接数(挂载
server.xml配置)。
3. 日志与监控
- 挂载日志目录到宿主机,便于持久化存储;
- 集成 ELK 栈收集日志,或 Prometheus + Grafana 监控容器状态。
4. 高可用(多实例)
- 启动多个 Java/Tomcat 容器,在 Nginx 配置中添加负载均衡:
http {# 负载均衡配置upstream java-servers {server java-app1:8080;server java-app2:8080;}# 转发时使用 upstream 名称location /api/ {proxy_pass http://java-servers/;} }
五、常见问题排查
1. Nginx 无法连接 Java 容器
- 检查容器是否在同一网络:
docker network inspect java-network,确认两个容器都在该网络; - 确认 Java/Tomcat 容器已启动(
docker compose ps状态为 Up); - 检查
proxy_pass配置:容器名是否正确(如java-app而非 IP),端口是否暴露。
2. Java 项目启动失败
- 查看容器日志:
docker compose logs -f java-app或tomcat-app,定位报错(如端口占用、依赖缺失); - 确认 JDK/Tomcat 版本与项目兼容(如 SpringBoot 2.x 不兼容 JDK 17+)。
3. WAR 包未自动解压
- 检查 WAR 包权限:确保宿主机
./tomcat/webapps/目录有读写权限; - 重启 Tomcat 容器:
docker compose restart tomcat-app。
六、核心总结
| 部署方式 | 适用场景 | 优势 | 关键注意点 |
|---|---|---|---|
| JAR 包 | SpringBoot 项目(内置 Tomcat) | 配置简单、无需额外 Tomcat | 确保 JAR 包可独立运行,暴露正确端口 |
| WAR 包 | 传统 Java Web 项目(SSM 等) | 兼容旧项目、可自定义 Tomcat | 注意 Tomcat 版本与 WAR 包兼容 |
核心优势:容器化部署隔离环境、Nginx 统一入口便于管理,通过 Docker Compose 简化多容器启停,适配开发/生产全场景。
