华为云ECS云服务器Nginx反向代理+SpringBoot自动化发布完整代码实战
一、开篇:从本地到云端,打通部署的最后一公里
前后端分离架构已经是现代Web应用开发的主流模式——后端通过SpringBoot提供RESTful API,前端使用Vue或React独立构建和部署。这种架构在开发阶段的效率优势毋庸置疑,但到了部署环节,很多开发者却卡在了所谓的“最后一公里”:后端jar包不知道放在哪里、前端dist文件不会配置Nginx、端口死活不通、跨域报错、页面白屏……折腾一整天可能连一个Hello World都跑不起来。
本文的目标就是彻底解决这个问题。我们将从一个典型的SpringBoot + Vue前后端分离项目出发,在华为云ECS上完整走完从零到上线的全过程。所有操作都基于真实的华为云控制台界面和Linux命令行,不跳步、不省略,文章会包含完整的配置文件代码和自动化部署脚本,你可以直接复制使用。
需要先登录华为云控制台,点击:华为云控制台,还没有账号,点击:注册并关联,已有账号点击:登录后关联
二、项目架构与技术选型
本文以典型的SpringBoot + Vue前后端分离项目为例:
- 后端:Spring Boot 2.7.x,Maven打包生成app.jar,内置Tomcat,默认端口8080
- 前端:Vue 3 + Vue Router + Axios,npm run build生成dist静态资源目录
- 通信方式:前端所有API请求以/api/开头,由Nginx反向代理转发至后端服务
- 运行环境:华为云ECS,操作系统选用CentOS 7.9或Ubuntu 22.04
在开始部署之前,我们先在本地确认项目可以正常运行。后端通过 mvn clean package 打出的jar包可以在本地通过 java -jar target/app.jar 启动,前端通过 npm run build 可以正确生成dist目录。这两步是后续所有部署操作的基础,务必在本地先验证通过。
三、华为云ECS实例的选购与创建
3.1 登录华为云控制台
访问华为云官网,点击右上角“控制台”进入管理界面。首次使用需要完成注册和实名认证,建议提前准备好身份证件和支付方式。
3.2 进入ECS购买页面
在控制台服务列表中选择“计算 > 弹性云服务器 ECS”,点击“购买弹性云服务器”进入购买页面。华为云提供了“快速购买”和“自定义购买”两种方式,新手建议从快速购买入手,后续可以根据需要调整配置。
3.3 关键配置项详解
- 计费模式:按需计费适合测试和学习,按小时结算;包年包月适合长期项目,价格更优惠。
- 区域与可用区:选择离目标用户最近的数据中心,可减少网络延迟。全国用户可选北京、上海或广州节点。注意不同区域的云服务产品之间内网互不相通,后续如果有多个云服务需要内网通信,必须选择同一区域。
- 实例规格:对于SpringBoot + Vue项目,推荐2核4GB起步——这个配置足够跑后端服务、Nginx和MySQL,留有余量避免内存溢出。如果预算有限,入门级的1核2GB也可以运行小型项目。
- 镜像选择:公共镜像推荐CentOS 7.9或Ubuntu 22.04,这两个系统生态成熟、教程最多。华为云也提供Huawei Cloud EulerOS,是华为自研的Linux发行版,对华为云服务有更好的优化。
- 系统盘:默认40GB起步,建议选择“通用型SSD”以获得较好的磁盘性能。
- 网络:系统会自动创建VPC和子网,保持默认即可。但务必为实例分配弹性公网IP(EIP),否则无法从公网访问服务器。
- 安全组:这是新手最容易忽略的配置。安全组相当于虚拟防火墙,控制进出服务器的流量。后续我们会详细配置,这里可以先选择默认安全组,创建完成后单独修改规则。
- 登录方式:强烈推荐使用密钥对登录,创建后会自动下载.pem私钥文件,需妥善保存。如果选择密码方式,密码需符合复杂度要求。
确认所有配置后点击“立即购买”,支付成功后等待1-3分钟,实例变为“运行中”状态即可使用。
四、安全组配置:开放必要端口
安全组是华为云上最重要的网络访问控制机制,很多新手部署项目时遇到“端口不通”的问题,十有八九是安全组没有配置正确。安全组由入方向规则和出方向规则共同组成,用来控制流入和流出安全组内实例的流量。
4.1 配置安全组规则
登录华为云控制台,进入ECS实例详情页,选择“安全组”页签,点击“配置规则”进入规则管理界面。
需要开放以下端口:
| 端口 | 协议 | 用途 | 源地址 |
|---|---|---|---|
| 22 | TCP | SSH远程连接 | 0.0.0.0/0(或限制为你的IP) |
| 80 | TCP | HTTP网站访问 | 0.0.0.0/0 |
| 443 | TCP | HTTPS网站访问 | 0.0.0.0/0 |
| 8080 | TCP | SpringBoot默认端口(可选,如果通过Nginx代理则可不开放) | 0.0.0.0/0 |
其中80和443端口是必须开放的,因为Nginx作为Web服务器需要监听这两个端口对外提供服务。SSH的22端口建议限制为你的本地IP地址,提高安全性。如果后端SpringBoot直接暴露给外网(不通过Nginx),则需要开放8080端口。
4.2 操作系统防火墙配置
除了云平台的安全组,操作系统本身也可能有防火墙(如firewalld)。如果安全组配置正确但仍然无法访问,可以检查系统防火墙状态:
# 检查防火墙状态
sudo systemctl status firewalld
# 如果防火墙开启,开放所需端口
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --reload
# 查看已开放的端口
sudo firewall-cmd --list-ports五、服务器基础环境搭建
ECS创建完成后,通过SSH连接到服务器。如果使用密钥对登录,命令格式为:
chmod 400 key.pem
ssh -i key.pem root@<你的公网IP>首次连接需输入yes确认指纹。如果使用密码登录:
ssh root@<你的公网IP>5.1 更新系统包
连接成功后,首先更新系统软件包到最新版本:
# CentOS/RHEL
sudo yum update -y
# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y5.2 安装JDK
SpringBoot应用需要Java运行环境,推荐使用OpenJDK 11或17:
# CentOS/RHEL 安装 OpenJDK 11
sudo yum install -y java-11-openjdk java-11-openjdk-devel
# Ubuntu/Debian 安装 OpenJDK 11
sudo apt install -y openjdk-11-jdk
# 验证安装
java -version5.3 安装MySQL数据库
如果项目需要数据库支持,可以在ECS上安装MySQL:
# CentOS/RHEL 安装 MySQL
sudo yum install -y mysql-server
sudo systemctl start mysqld
sudo systemctl enable mysqld
# Ubuntu/Debian 安装 MySQL
sudo apt install -y mysql-server
sudo systemctl start mysql
sudo systemctl enable mysql
# 查看MySQL运行状态
sudo systemctl status mysql
# 初始化安全设置(设置root密码、删除匿名用户等)
sudo mysql_secure_installation数据库安装完成后,需要创建项目所需的数据库和用户,并导入初始数据。注意生产环境不建议使用root账户直接操作应用数据库,应创建独立的应用账号并授予最小必要权限。
5.4 安装Nginx
Nginx是前后端分离部署中的核心组件,既作为前端静态资源的Web服务器,也作为后端API的反向代理:
# CentOS/RHEL 安装 Nginx
sudo yum install -y epel-release
sudo yum install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# Ubuntu/Debian 安装 Nginx
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# 验证Nginx是否正常运行
curl http://localhost安装完成后,通过浏览器访问服务器公网IP,如果看到Nginx欢迎页面,说明安装成功。
六、部署后端SpringBoot应用
6.1 打包SpringBoot项目
在本地开发环境中,使用Maven将SpringBoot项目打包成可执行的jar文件:
mvn clean package -DskipTests打包完成后,target目录下会生成一个jar文件(如app.jar)。
6.2 上传jar包到服务器
有多种方式可以将jar包上传到ECS:
- scp命令:
scp -i key.pem target/app.jar root@<公网IP>:/opt/ - rsync:支持断点续传,适合大文件
- 图形化工具:如FinalShell、WinSCP等
建议在服务器上创建专门的部署目录:
sudo mkdir -p /opt/myapp
sudo chown -R root:root /opt/myapp6.3 启动SpringBoot应用
上传完成后,通过以下命令启动应用:
cd /opt/myapp
java -jar app.jar但这种启动方式在前台运行,关闭SSH会话后应用就会停止。生产环境需要使用后台运行方式:
nohup java -jar app.jar > app.log 2>&1 &或者使用更专业的进程管理工具如systemd或supervisor来管理SpringBoot进程,支持开机自启和异常重启。
6.4 使用systemd管理SpringBoot服务
创建systemd服务文件,实现进程守护和开机自启:
sudo vim /etc/systemd/system/myapp.service写入以下内容:
[Unit]
Description=My SpringBoot Application
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/java -jar /opt/myapp/app.jar
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target然后执行:
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp七、部署前端Vue应用
7.1 构建Vue项目
在本地开发环境中执行构建命令:
npm run build构建完成后会生成dist目录,里面包含所有静态资源文件(HTML、CSS、JavaScript、图片等)。
7.2 上传dist到服务器
将dist目录上传到服务器的指定位置:
sudo mkdir -p /var/www/myapp
# 使用scp上传dist目录中的所有文件
scp -r dist/* root@<公网IP>:/var/www/myapp/7.3 配置Nginx提供静态资源服务
在 /etc/nginx/conf.d/ 目录下创建项目配置文件:
sudo vim /etc/nginx/conf.d/myapp.conf写入以下基础配置:
server {
listen 80;
server_name _; # 使用_匹配所有域名,生产环境建议替换为实际域名
root /var/www/myapp;
index index.html;
charset utf-8;
# Vue Router History模式支持
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存优化
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}配置完成后,测试并重载Nginx:
sudo nginx -t
sudo systemctl reload nginx此时通过浏览器访问服务器公网IP,应该可以看到前端页面。但此时API请求还无法正常工作,因为后端接口还没有被代理。
八、Nginx反向代理配置——前后端联调
反向代理是Nginx最核心的功能之一。简单来说,正向代理代理的是客户端(如VPN),而反向代理代理的是服务器。对于用户来说,不需要关心请求被转发到哪台后端服务器,只需要把请求发给Nginx即可,Nginx负责将请求路由到正确的后端服务。
8.1 完整的Nginx配置
修改 /etc/nginx/conf.d/myapp.conf,加入反向代理配置:
server {
listen 80;
server_name _;
# 前端静态文件
root /var/www/myapp;
index index.html;
charset utf-8;
# Vue Router History模式
location / {
try_files $uri $uri/ /index.html;
}
# 后端API反向代理
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时配置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}8.2 配置解读
- location /:处理所有非静态资源的请求,配合
try_files指令实现Vue Router的History模式——当请求的路径不存在时,返回index.html,由前端路由接管。 - location /api/:将所有以
/api/开头的请求转发到后端的SpringBoot服务(127.0.0.1:8080)。这里的/api/是前端统一配置的API请求前缀,后端接口路径中不应包含这个前缀,或者使用rewrite指令去除前缀。 - proxy_set_header:设置转发请求的头部信息,确保后端能够获取到客户端的真实IP。
- 静态资源缓存:对图片、CSS、JS等静态资源设置较长的缓存时间,减少重复请求,提升页面加载速度。
8.3 负载均衡配置(扩展)
如果部署了多个SpringBoot实例,可以使用Nginx的upstream实现负载均衡:
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
# ... 其他配置
location /api/ {
proxy_pass http://backend/;
# ... 其他proxy设置
}
}默认使用轮询策略,也可以配置权重、ip_hash等负载均衡算法。
九、自动化发布方案
手动部署的流程虽然清晰,但每次发布都需要重复执行打包、上传、重启等操作,效率低下且容易出错。自动化发布可以显著提升部署效率,降低人为失误。下面提供三种不同层次的自动化方案。
9.1 Shell脚本自动化部署
编写一个Shell脚本,将打包、上传、重启等步骤整合在一起。在服务器上创建部署脚本 /opt/deploy.sh:
#!/bin/bash
# 部署脚本 - 用于自动化发布SpringBoot应用
APP_NAME="myapp"
APP_DIR="/opt/myapp"
JAR_NAME="app.jar"
BACKUP_DIR="/opt/backup"
LOG_DIR="/var/log/myapp"
# 创建必要的目录
mkdir -p $BACKUP_DIR
mkdir -p $LOG_DIR
# 备份当前版本
if [ -f "$APP_DIR/$JAR_NAME" ]; then
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
cp $APP_DIR/$JAR_NAME $BACKUP_DIR/${JAR_NAME}_$TIMESTAMP
echo "已备份当前版本到 $BACKUP_DIR/${JAR_NAME}_$TIMESTAMP"
fi
# 停止当前服务
sudo systemctl stop $APP_NAME
# 移动新jar包(假设已上传到/tmp目录)
if [ -f "/tmp/$JAR_NAME" ]; then
mv /tmp/$JAR_NAME $APP_DIR/
echo "新版本已部署到 $APP_DIR/$JAR_NAME"
else
echo "错误:未找到新jar包 /tmp/$JAR_NAME"
exit 1
fi
# 启动服务
sudo systemctl start $APP_NAME
# 等待服务启动
sleep 5
# 检查服务状态
if sudo systemctl is-active --quiet $APP_NAME; then
echo "✅ 部署成功!服务已启动"
else
echo "❌ 部署失败,请检查日志"
sudo systemctl status $APP_NAME
exit 1
fi赋予执行权限:
chmod +x /opt/deploy.sh9.2 Git钩子(Git Hooks)自动部署
在服务器上配置Git仓库的post-receive钩子,当代码推送到服务器时自动触发部署。
在服务器上初始化一个裸仓库:
mkdir -p /opt/git/myapp.git
cd /opt/git/myapp.git
git init --bare创建post-receive钩子:
vim /opt/git/myapp.git/hooks/post-receive写入以下内容:
#!/bin/bash
# Git post-receive 钩子 - 自动部署
WORK_TREE="/opt/myapp_temp"
DEPLOY_SCRIPT="/opt/deploy.sh"
export GIT_WORK_TREE=$WORK_TREE
export GIT_DIR=/opt/git/myapp.git
# 检出最新代码
mkdir -p $WORK_TREE
git checkout -f
# 进入工作目录并构建
cd $WORK_TREE
mvn clean package -DskipTests
# 复制jar包到部署位置
cp target/*.jar /tmp/app.jar
# 执行部署脚本
$DEPLOY_SCRIPT
echo "✅ Git钩子部署完成"赋予执行权限:
chmod +x /opt/git/myapp.git/hooks/post-receive在本地配置远程仓库:
git remote add deploy root@<公网IP>:/opt/git/myapp.git每次推送代码时,执行 git push deploy main,就会自动触发服务器端的构建和部署流程。
9.3 华为云CodeArts流水线部署
华为云提供了CodeArts DevOps平台,支持可视化的流水线编排,实现从代码提交到自动部署的全流程自动化。
基本流程:
- 在CodeArts中创建项目,关联代码仓库(华为云代码托管或GitHub)
- 配置编译构建任务:拉取代码、Maven构建、打包成jar
- 配置部署任务:选择ECS部署模板,指定目标服务器和部署路径
- 创建流水线:将构建和部署串联起来,设置触发条件(如代码提交自动触发)
CodeArts部署服务提供了SpringBoot系统模板,可以快速创建部署应用,支持可视化编排和并行部署。这种方式不需要自己编写脚本,适合企业级项目的持续交付。
9.4 前端自动化部署
前端的自动化部署同样重要,可以编写脚本实现自动构建和发布:
#!/bin/bash
# 前端部署脚本
FRONTEND_DIR="/opt/frontend"
NGINX_ROOT="/var/www/myapp"
export GIT_WORK_TREE=$FRONTEND_DIR
export GIT_DIR=/opt/git/frontend.git
# 检出最新代码
git checkout -f
# 安装依赖并构建
cd $FRONTEND_DIR
npm install
npm run build
# 部署到Nginx目录
sudo rm -rf $NGINX_ROOT/*
sudo cp -r dist/* $NGINX_ROOT/
# 重载Nginx
sudo systemctl reload nginx
echo "✅ 前端部署完成"十、常见问题与排障指南
10.1 端口不通
这是最常遇到的问题。检查顺序:安全组规则是否正确开放了端口 → 操作系统防火墙是否开放了端口 → 服务进程是否在监听该端口 → 服务是否正常运行。
使用 ss -nutlp | grep :80 或 netstat -tlnp | grep :80 查看端口监听状态。
10.2 页面白屏或404
Vue项目部署后页面白屏,通常是Nginx的 try_files 配置不正确,或者dist文件没有放到正确的路径。检查Nginx配置中的root路径是否指向dist目录,以及 try_files $uri $uri/ /index.html; 是否正确配置。
10.3 API请求404或跨域
API请求404,检查Nginx的 location /api/ 配置中的 proxy_pass 地址是否正确,以及后端的接口路径是否与请求路径匹配。如果前端请求的是 /api/user,后端接口是 /user,需要在Nginx中做路径重写。
跨域问题在前后端分离项目中很常见,通过Nginx反向代理可以彻底解决——前端请求的是同一个域名和端口,不存在跨域问题。
10.4 服务启动失败
SpringBoot启动失败,查看日志文件:
sudo journalctl -u myapp -f
# 或查看应用日志
tail -f /opt/myapp/app.log常见原因:端口被占用、数据库连接失败、配置文件错误等。
十一、总结与最佳实践
本文完整覆盖了在华为云ECS上部署SpringBoot+Vue前后端分离项目的全流程,从服务器购买、安全组配置、环境安装,到应用部署、Nginx反向代理配置,再到自动化发布方案的实现。整个过程涉及的技术栈包括:
- 基础设施:华为云ECS、弹性公网IP、安全组
- 运行环境:JDK 11、MySQL、Nginx
- 应用部署:SpringBoot jar包、Vue dist静态资源
- 服务治理:Nginx反向代理、负载均衡
- 自动化:Shell脚本、Git钩子、CodeArts流水线
几点最佳实践建议:
- 生产环境务必使用域名和HTTPS,Nginx可以配置SSL证书实现加密传输
- 数据库等有状态服务建议使用华为云RDS等托管服务,比自建更稳定安全
- 使用systemd管理应用进程,实现开机自启和异常自动重启
- 建立完善的日志收集和监控告警机制
- 自动化部署脚本中加入版本回滚功能,应对发布异常
希望这份实战指南能帮助你顺利完成项目的云上部署。从本地开发到线上运行,这最后一公里的路,走通了就是质变。
常见问答
问1:华为云ECS的安全组和操作系统防火墙有什么区别?
安全组是华为云平台层面的网络访问控制,在流量进入ECS之前进行过滤;操作系统防火墙(如firewalld、iptables)是ECS内部的服务,在流量到达系统之后进行过滤。两者是叠加关系,任何一个环节拦截都会导致访问失败。建议优先在安全组配置规则,操作系统防火墙保持默认或根据实际需要调整。
问2:前后端分离项目中,Nginx反向代理的核心作用是什么?
Nginx反向代理在前后端分离架构中有两个核心作用:一是作为静态资源服务器直接提供前端HTML/CSS/JS等文件的访问;二是将前端发起的API请求转发到后端的SpringBoot服务,从而解决跨域问题,同时实现负载均衡和请求路由。通过Nginx,前端和后端可以使用同一域名和端口对外提供服务,用户体验更统一。
问3:SpringBoot应用在云服务器上如何实现开机自启?
推荐使用systemd服务管理器。在 /etc/systemd/system/ 目录下创建服务的.service文件,配置ExecStart为java -jar命令,然后执行 systemctl enable 服务名 即可实现开机自启。相比nohup方式,systemd提供了更完善的进程管理和日志记录功能。
问4:自动化部署脚本中为什么要做版本备份?
版本备份是为了支持快速回滚。当新版本部署后出现严重问题时,可以迅速恢复到上一个稳定版本,减少服务中断时间。备份策略通常保留最近3-5个版本,并按照日期时间命名,便于追溯。在自动化脚本中加入备份逻辑是生产环境部署的标准实践。
问5:Git钩子自动部署和华为云CodeArts流水线各有什么优缺点?
Git钩子方式轻量简单,不需要额外平台,适合个人或小团队项目,但缺乏可视化的编排和监控能力。CodeArts流水线是专业级DevOps平台,提供可视化编排、多步骤并行、权限管理、构建缓存、部署日志等完整功能,适合企业级项目,但需要学习和使用华为云CodeArts服务。两者可以根据项目规模和团队能力选择,也可以组合使用。
问6:部署后页面能打开但API请求报错500,如何排查?
500错误是服务器内部错误,问题通常在后端。首先查看SpringBoot的应用日志,确认具体异常堆栈;然后检查数据库连接是否正常、配置文件中的参数是否正确、依赖的外部服务是否可达。如果日志中没有明显错误,可以检查Nginx是否正确将请求转发到了后端,以及后端是否监听了正确的端口。



