背景知识
Tomcat
Tomcat 是 Apache 旗下的开源 Java Servlet 容器,核心实现了 Servlet/JSP 规范,同时内置了轻量级 HTTP 服务器,能封装 HTTP 协议的底层通信逻辑。开发者无需关注网络通信细节,只需编写 Servlet/Controller、页面模板(如 JSP/FreeMarker)等业务逻辑,即可让浏览器通过 HTTP 协议访问后端资源。
Tomcat 的设计核心是支撑 Java 动态 Web 应用(如 Spring MVC 项目),对静态资源的处理效率远低于专业的 HTTP 服务器(如 Nginx);同时 Tomcat 仅提供单节点的 Web 服务能力,无法原生实现 负载均衡、高可用、动静分离等生产级运维能力,需依赖外部组件(如 Nginx、LVS)补充。
Nginx
Nginx 是一款轻量级的高性能 HTTP / 反向代理服务器,核心优势是内存占用低、并发处理能力强(基于异步非阻塞 I/O 模型),目前国内 BAT、字节等大厂均将其作为 Web 端核心中间件。
Nginx 的核心生产级功能包括:负载均衡、动静分离、正向代理、反向代理、请求限流、SSL 证书配置、缓存等,核心功能解释如下:
- 正向代理 :代理的是客户端,客户端主动配置代理服务器地址,所有请求先发给代理服务器,再由代理转发到目标服务器(典型场景:翻墙、内网客户端访问外网);
- 反向代理 :代理的是服务端,客户端无感知代理的存在,请求先发给 Nginx,由 Nginx 根据规则转发到后端的一台 / 多台应用服务器(典型场景:隐藏后端服务地址、负载均衡);
- 动静分离:Nginx 将静态资源(HTML/CSS/JS/ 图片)请求直接处理返回,动态请求(如接口、JSP)转发给 Tomcat,利用 Nginx 的高性能提升静态资源访问效率;
- 负载均衡:将客户端请求均匀分发到多台后端 Tomcat 服务器,避免单台服务器过载,提升系统并发能力和可用性。
Nginx的安装只需以下命令
sudo apt update
sudo apt upgrade # 更新软件包,避免版本问题
sudo apt install -y curl gnupg2 ca-certificates lsb-release # 安装前置包
sudo apt install -y nginx # 安装nginx
sudo systemctl start nginx # 启动nginx
sudo systemctl enable nginx # 设置开机自启动
输入本机网址见到如下页面说明安装成功:

Docker
docker通过核心技术Namespace命名空间隔离、Control Group控制组资源限制、Union Filesystem联合文件系统,实现了应用层面的隔离,其隔离性比虚拟机若,但占用资源也比虚拟机小,得益于其可以独立部署的优点,现在在服务分发领域应用广泛。
| 核心技术 | 作用 | 概括 |
|---|---|---|
| Namespace 命名空间 | 通过命名空间,隔离用户、进程、网络、使用空间等维度,让容器具有独立性 | 给应用搭建单独空间,避免外部干扰 |
| Control Group 控制组 | 将进程按组管理,防止无限申请资源 | 应用独立分配资源 |
| Union Filesystem 联合文件系统 | 将物理位置不同的文件挂载到一个目录,达到从逻辑上是一个整体文件系统的效果,便于镜像复用和分层存储 | 基础层共用,修改只加新层,不改动底层 |
docker常用命令如下:
搜索镜像 docker search 名称
下载镜像 docker pull 名称:标签
查看镜像 docker images
导出镜像 docker save 名称 -o或> 文件名称
导入镜像 docker load -i或< 名称
创建容器 docker create
启动容器 docker start
创建并启动 docker run
显示容器 docker ps -a
端口映射 -P随机映射 -p 指定端口:容器目的端口
查看映射端口 docker port
暂停容器 docker pause
停止容器 docker stop
制作镜像通常使用dockerfile,常用方法如下:
FROM 指定基础镜像,用于后续的指令构建。
MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 在构建过程中在镜像中执行命令。
CMD 指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL复制到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。
测试项目
使用Spring构建的简单项目,就是映射到指定路径的静态资源文件:
java
@Controller
public class IndexController {
@GetMapping("/index")
public String index() {
// 后续完善页面内容
return "welcome";
}
@GetMapping("/login")
public String login() {
return "login";
}
}
xml
// properties中配置前后缀自动访问
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=.ftl
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
body {
background: linear-gradient(120deg, #89f7fe 0%, #66a6ff 100%);
min-height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', 'Arial', sans-serif;
}
.welcome-container {
background: rgba(255,255,255,0.95);
padding: 40px 50px;
border-radius: 18px;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15), 0 2px 4px rgba(97, 144, 232, 0.12);
text-align: center;
max-width: 400px;
}
/*后续略*/

项目部署
命令行部署
SpringBoot的特点是内部整合启动器,所有依赖高内聚,打包成jar后可独立部署运行。
打包流程为:
- pom.xml中取消跳过打包逻辑,将
<skip>true</skip>注释掉,该命令负责跳过打包逻辑;
- 打包成jar,用
Maven的package命令即可;
- 启动jar包,命令
java -jar 包路径;
这种部署简便、轻量,可用以下命令指定具体细节:
# 后台运行(Linux/Mac,否则随控制台退出),输出日志到app.log
nohup java -jar your-spring-boot-app.jar > app.log 2>&1 &
# 指定端口启动
java -jar your-spring-boot-app.jar --server.port=8081
# 指定配置文件启动(覆盖默认配置)
java -jar your-spring-boot-app.jar --spring.config.location=./application-prod.properties
但核心缺陷是缺少生产级保障,主要有以下几点:
- 进程无守护:应用崩溃后不会自动重启(比如 OOM、网络异常导致退出);
- 无负载均衡:单实例部署,并发瓶颈明显,无法水平扩展;
- 启停不优雅:直接 kill 进程可能导致请求中断,无优雅停机;
- 无监控告警:无法实时监控应用状态(如内存、CPU、接口耗时),故障无法及时发现。
Nginx代理
为了给tomcat服务增加健壮性,生产项目中通常采用nginx代理,流量先打到nginx上,这样做主要有两个好处:
- 实现生产级健壮性保证,nginx作为网关实现负载均衡等功能;
- 保护内网服务,具体后端服务可以设置在内网上,外部流量经过nginx转发,而无法直接获取内网资源。
使用Nginx代理Tomcat服务器命令如下:
# 后端Tomcat节点池配置
upstream tomcat_server { # 自定义后端服务器池
server 127.0.0.1:8080 weight=1; # Tomcat实例地址,weight为权重,越大转发越多
server 127.0.0.1:8081 weight=2; # 可配置多个地址用于负载均衡
server 192.168.1.100:8080 backup; # backup备份,所有地址都挂了转发到此
keepalive 4; # 长连接保持数量,类似线程池,避免重复创建链接的开销
}
# Nginx虚拟主机配置
server {
listen 8081; # 监听端口,推荐修改,否则可能被更高优先级的占用80
server_name 127.0.0.1; # 访问指定请求域名,匹配该主机规则
# 一个服务器可能绑定多个域名,通过server_name分流,单域名可避免手动构造转发
# 请求转发规则
location / {
proxy_pass http://tomcat_server; # 匹配请求转发到后端节点池
proxy_set_header Host $host; # 传递Host请求头,客户访问域名传给Tomcat
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递代理链IP
proxy_connect_timeout 60s; # 连接超时
proxy_read_timeout 60s; # 读取超时
proxy_send_timeout 60s; # 发送超时
}
}
上述命令写在新建配置文件/etc/nginx/conf.d/tomcat.conf中,会被主配置文件/etc/nginx/nginx.conf自动加载。

最后使用如下命令检查并重启nginx即可:
shell
sudo nginx -t # 检查配置文件语法问题,如果输出ok和successful说明修改没有语法错误
sudo systemctl restart nginx # 重启nginx服务
输入不同url可见相同界面,证明消息成功被nginx转发

docker容器部署
如果是集群上线程序,使用传统jar+nginx部署的方式就变得十分繁琐,此时需要引入docker容器。
这里的重点是使用dockerfile制作镜像,新建dockerfile文件至jar包相同目录,命令及说明如下:
# 1. 选择基础镜像:推荐轻量的JRE镜像(避免全量JDK,减小镜像体积)
# 注意:JDK版本要和应用兼容(比如应用用JDK8,就选openjdk:8-jre-slim)
FROM openjdk:17
# 2. (可选)设置容器内的工作目录(类似cd命令,后续命令基于此目录执行)
WORKDIR /app
# 3. 将服务器上的jar包复制到容器的/app目录下(左边是服务器路径,右边是容器路径)
# 注意:替换成你的jar包名称
COPY system-0.0.1-SNAPSHOT.jar /app/app.jar
# 4. 暴露应用运行的端口(和Spring Boot配置的server.port一致,比如8081)
EXPOSE 8081
# 5. 容器启动时执行的命令(启动Java应用)
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
使用如下命令进行构建:
# 格式:docker build -t 镜像名:版本号 .
docker build -t java-demo:v1.0 .
随后使用如下命令启动:
# 格式:docker run -d -p 宿主机端口:容器端口 --name 容器名 镜像名:版本
docker run -d -p 8081:8081 --name demo-app java-demo:v1.0
总结
本文学习了三种 SpringBoot 的部署方式,命令行、Nginx 代理增强部署、Docker 容器化部署,适用场景随并发量、集群规模和生产级要求的提升依次递进:
- 命令行部署:操作最简单,仅需打包 Jar 包后用java -jar启动,但缺乏生产级保障(无进程守护、无负载均衡、启停不优雅),仅适用于开发 / 测试环境或低并发单机场景;
- Nginx 代理部署:以 Nginx 作为流量网关,实现负载均衡、动静分离、隐藏后端服务等生产级能力,解决了单 Tomcat 并发瓶颈和服务暴露问题,但集群部署时需逐台配置环境并启动 Jar,运维成本随节点数增加显著上升;
- Docker 容器化部署:本质是将 Jar 包 + 运行环境(JRE / 系统依赖)封装为镜像,彻底解决环境不一致问题,结合 K8s 可实现集群的自动化部署,适配中大型公司的规模化运维需求;且 Docker+K8s 仍需搭配 Nginx(作为前端网关),负责外部流量分发、SSL 配置等网关级能力。