华为云Web项目部署实战:从服务器配置到安全上线的完整指南

华为云Web项目部署实战:从服务器配置到安全上线的完整指南

1. 从本地到云端:为什么选择华为云部署你的Web项目?

如果你已经完成了一个Web项目,无论是用Vue、React写的前端单页应用,还是Spring Boot、Django开发的后端服务,让它仅仅运行在localhost:8080上,总感觉少了点什么。没错,是时候让它真正“上线”,接受互联网的检验了。部署,就是将你电脑里的代码,搬到一台24小时不间断运行的远程服务器上,并配置好网络、域名,让全世界都能通过一个网址访问到它的过程。这听起来有点复杂,但别担心,今天我们就来彻底拆解这个过程,手把手带你走一遍。

为什么选择华为云作为我们这次实战的平台?原因有几个。首先,作为国内主流的云服务商,华为云提供了从虚拟机(弹性云服务器ECS)到数据库、对象存储、CDN等一整套完整的云产品线,生态成熟,文档和社区支持也比较完善。其次,对于个人开发者或中小团队,华为云经常有针对新用户的优惠活动,初期成本可控。最后,其控制台界面相对清晰,操作逻辑与阿里云、腾讯云等大同小异,掌握了其中一家的部署流程,迁移到其他平台也会触类旁通。当然,部署的核心逻辑是相通的,无论你最终选择哪家云厂商,这篇文章中关于服务器配置、环境搭建、应用发布、安全加固的思路都具有普适性。

在开始之前,我们需要明确这次部署的目标:不是简单地“把项目跑起来”,而是构建一个稳定、安全、可维护的线上环境。这意味着我们要考虑服务的高可用性(比如进程守护)、数据的安全性(如防火墙配置)、以及后续更新的便捷性(如自动化部署脚本)。我们将以一个典型的“前后端分离”项目为例,前端是打包后的静态文件,后端是一个Java Spring Boot应用,数据库使用MySQL。这个架构非常普遍,能覆盖大多数场景。

2. 战前准备:理清部署架构与资源清单

动手操作之前,盲目地点下一步是最危险的。我们必须先画一张“作战地图”,明确我们需要什么,以及它们之间的关系。一个最小化的可访问Web部署,通常包含以下核心组件:

  1. 计算资源(服务器):一台云服务器(ECS),这是承载你应用代码的“电脑”。你需要选择它的配置(CPU、内存)、操作系统(通常选Linux,如CentOS 7.9或Ubuntu 20.04)、以及网络(公网IP、带宽)。
  2. 网络与安全:安全组(防火墙规则),用于控制哪些端口(如80-HTTP, 443-HTTPS, 22-SSH)可以被外界访问。域名(如果需要),以及将域名解析到服务器公网IP的DNS配置。
  3. 运行环境:你的代码赖以生存的软件环境。对于Java后端,需要JDK;对于Python后端,需要Python解释器和pip;对于前端,可能需要Nginx来提供静态文件服务和反向代理。
  4. 数据存储:数据库。你可以选择在同一个服务器上安装MySQL(节省成本,但增加服务器负担),或者使用云厂商提供的云数据库RDS(更稳定、易维护,但单独计费)。
  5. 应用本身:打包好的前端静态文件(如dist文件夹)和后端可执行Jar包(或War包)。

基于以上,我建议的部署架构如下:

用户浏览器 <--(HTTP/HTTPS)--> [云服务器 ECS] | |--- Nginx (监听80/443端口) | | | |--- 反向代理到后端服务 (如 localhost:8080) | |--- 直接服务前端静态文件 | |--- 后端Java应用 (运行在8080端口) | |--- MySQL数据库 (运行在3306端口,仅本地访问)

在这个架构里,Nginx扮演了“门卫”和“路由员”的角色。它对外接收所有Web请求,如果是请求前端页面或静态资源(JS、CSS、图片),它就直接从服务器磁盘上读取并返回;如果是请求后端API(通常以/api开头),它就把请求转发给内部运行在8080端口的Java应用。这样做的好处是,前端和后端对外只有一个入口(80端口),更安全,也便于做负载均衡和HTTPS配置。

资源清单与选型建议:

  • 服务器:个人博客或小型演示项目,1核2GB内存的配置通常足够。选择CentOS 7.9Ubuntu 20.04 LTS,它们社区支持强大,教程也多。务必在购买时分配一个公网IP,并设置一个复杂的root密码或直接使用密钥对登录(更安全)。
  • 安全组:初期开放三个端口即可:22(SSH,用于远程连接)、80(HTTP)、443(HTTPS)。3306(MySQL)端口绝对不要对公网开放。
  • 域名(可选):如果你希望用户通过www.yourname.com访问,而不是难记的IP地址,就需要购买一个域名,并在域名服务商那里添加一条A记录,指向你的服务器公网IP。

理清了这些,我们就可以登录华为云控制台,开始具体的操作了。

3. 服务器初始化:安全登录与基础环境搭建

拿到一台崭新的云服务器,就像拿到一台刚装好操作系统的电脑,我们需要进行一系列初始化设置,为后续部署铺平道路。

3.1 远程连接与安全加固

首先,通过华为云控制台找到你的ECS实例,记下它的公网IP。我们使用SSH协议进行远程连接。在Windows上,可以使用PuTTY或Windows Terminal;在Mac或Linux上,直接使用终端。

ssh root@你的服务器公网IP

输入你购买时设置的密码,即可登录。首次登录后,强烈建议做以下几件事:

  1. 更新系统软件包:确保系统组件是最新的,修复已知漏洞。

    # 对于CentOS yum update -y # 对于Ubuntu apt update && apt upgrade -y
  2. 创建新用户并授予sudo权限:长期使用root用户操作是高风险行为。创建一个日常使用的普通用户。

    # 添加一个名为 `deploy` 的用户 adduser deploy # 为deploy用户设置密码 passwd deploy # 将deploy用户添加到wheel组(CentOS)或sudo组(Ubuntu),使其能使用sudo命令 usermod -aG wheel deploy # CentOS # usermod -aG sudo deploy # Ubuntu
  3. 配置SSH密钥登录(可选但推荐):相比密码,密钥登录更安全。在你的本地电脑生成密钥对(如果还没有的话):

    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

    默认会在~/.ssh/目录下生成id_rsa(私钥,妥善保管)和id_rsa.pub(公钥)。将公钥内容上传到服务器的deploy用户目录下。

    # 在本地终端执行,将公钥上传到服务器 ssh-copy-id -i ~/.ssh/id_rsa.pub deploy@你的服务器公网IP

    之后,你就可以使用ssh deploy@你的服务器公网IP无需密码直接登录。为了进一步提升安全,可以禁用root用户的SSH密码登录。编辑SSH配置文件:

    sudo vi /etc/ssh/sshd_config

    找到并修改以下两行:

    PermitRootLogin no # 禁止root登录 PasswordAuthentication no # 禁止密码认证(确保密钥登录已成功后再设置!)

    保存后重启SSH服务:sudo systemctl restart sshd

3.2 安装必备软件:JDK、MySQL与Nginx

现在,我们以deploy用户身份,安装运行环境。

安装JDK (以Java 11为例)

# CentOS sudo yum install -y java-11-openjdk-devel # Ubuntu sudo apt install -y openjdk-11-jdk # 验证安装 java -version

安装MySQL (以MySQL 8.0为例): MySQL的安装稍微复杂,需要添加官方仓库。

# CentOS 7 sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm sudo yum install -y mysql-community-server # Ubuntu 20.04 wget https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb sudo dpkg -i mysql-apt-config_0.8.22-1_all.deb # 弹出框选择OK和MySQL8.0 sudo apt update sudo apt install -y mysql-server

安装完成后,启动并设置开机自启:

sudo systemctl start mysqld sudo systemctl enable mysqld

MySQL 8.0在首次启动时会生成一个临时root密码,需要查看日志获取:

sudo grep 'temporary password' /var/log/mysqld.log

使用该密码登录,并立即修改密码,同时创建一个用于你应用程序的数据库和用户:

mysql -uroot -p
-- 输入临时密码后,修改root密码 ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPassword123!'; -- 创建一个新数据库 CREATE DATABASE your_app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建一个应用专用用户,并授予其对该数据库的所有权限 CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'AnotherStrongPassword456!'; GRANT ALL PRIVILEGES ON your_app_db.* TO 'app_user'@'localhost'; FLUSH PRIVILEGES; EXIT;

关键安全点'app_user'@'localhost'中的localhost意味着这个用户只能从服务器本机连接,杜绝了从外网直接访问数据库的可能。密码务必设置得足够复杂。

安装Nginx

# CentOS (需先安装EPEL仓库) sudo yum install -y epel-release sudo yum install -y nginx # Ubuntu sudo apt install -y nginx # 启动并设置开机自启 sudo systemctl start nginx sudo systemctl enable nginx

安装完成后,在浏览器访问你的服务器公网IP,如果看到Nginx的欢迎页面,说明安装成功且安全组的80端口已开放。

4. 应用部署实战:上传、配置与启动

环境就绪,现在轮到主角——你的Web应用登场了。我们需要将本地打包好的文件上传到服务器,并进行配置。

4.1 文件上传与目录规划

首先,在服务器上创建一个清晰的目录结构来存放你的应用。我习惯在/home/deploy/apps/下为每个项目建立独立目录。

sudo mkdir -p /home/deploy/apps/your-project sudo chown -R deploy:deploy /home/deploy/apps/your-project

接下来,从本地将文件上传到服务器。可以使用scp命令(在本地终端执行):

# 上传前端dist目录 scp -r /本地路径/your-project-frontend/dist/* deploy@你的服务器公网IP:/home/deploy/apps/your-project/frontend/ # 上传后端Jar包 scp /本地路径/your-project-backend/target/your-app.jar deploy@你的服务器公网IP:/home/deploy/apps/your-project/backend/

如果文件较大或较多,也可以考虑使用rsync(支持增量同步)或通过Git直接在服务器上拉取代码(需在服务器安装Git)。

4.2 后端Spring Boot应用配置与启动

进入后端目录,我们需要配置应用连接数据库,并以服务的形式运行它,确保崩溃后能自动重启。

  1. 准备配置文件:通常Spring Boot的配置文件application-prod.ymlapplication.properties会包含数据库连接信息。你可以直接上传这个文件,或者在启动时通过命令行参数指定。为了安全,不要把包含密码的配置文件提交到Git,而是在服务器上创建。

    cd /home/deploy/apps/your-project/backend vi application-prod.yml

    内容示例:

    spring: datasource: url: jdbc:mysql://localhost:3306/your_app_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: app_user password: AnotherStrongPassword456! # 使用之前创建的数据库用户密码 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update # 根据实际情况选择,生产环境慎用`create` show-sql: true server: port: 8080 address: 127.0.0.1 # 只监听本地回环地址,防止外部直接访问

    注意server.address: 127.0.0.1这个配置至关重要,它让后端服务只允许本机(即Nginx)访问,构成了一个简单的内部网络隔离。

  2. 将应用注册为系统服务:使用systemd来管理,这是最可靠的方式。创建服务文件:

    sudo vi /etc/systemd/system/your-app.service

    写入以下内容(根据你的路径和Jar包名修改):

    [Unit] Description=Your Spring Boot Application After=syslog.target network.target mysqld.service [Service] User=deploy Group=deploy WorkingDirectory=/home/deploy/apps/your-project/backend ExecStart=/usr/bin/java -jar -Dspring.profiles.active=prod your-app.jar SuccessExitStatus=143 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
    • UserGroup指定了以哪个用户身份运行,这里用我们创建的deploy,避免使用root。
    • WorkingDirectory指定了工作目录,这样应用生成的日志等文件都会在这个目录下。
    • ExecStart是启动命令,-Dspring.profiles.active=prod指定使用生产环境配置。
    • Restart=always确保应用意外退出时会自动重启。
  3. 启动并检查服务

    sudo systemctl daemon-reload # 重载systemd配置 sudo systemctl start your-app # 启动服务 sudo systemctl enable your-app # 设置开机自启 sudo systemctl status your-app # 查看服务状态

    如果状态显示active (running),并且用curl localhost:8080/your-health-endpoint(如果有健康检查接口)能收到响应,说明后端启动成功。

4.3 前端静态文件与Nginx核心配置

现在配置Nginx,让它同时承担静态文件服务和反向代理。

  1. 删除默认配置(可选):

    sudo rm /etc/nginx/conf.d/default.conf
  2. 为你的项目创建Nginx配置文件

    sudo vi /etc/nginx/conf.d/your-project.conf

    写入以下配置:

    server { listen 80; server_name your-domain.com www.your-domain.com; # 如果没有域名,这里可以写服务器公网IP或下划线_ # 前端静态文件服务 location / { root /home/deploy/apps/your-project/frontend; index index.html index.htm; try_files $uri $uri/ /index.html; # 单页应用History模式的关键配置 } # 反向代理到后端API location /api/ { proxy_pass http://127.0.0.1:8080/; # 注意结尾的斜杠,它会将/api/前缀传递给后端 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; } # 可选:静态资源缓存优化 location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ { root /home/deploy/apps/your-project/frontend; expires 30d; add_header Cache-Control "public, immutable"; } }

    这个配置做了几件关键事:

    • listen 80:监听HTTP请求。
    • root:指定前端文件存放的根目录。
    • try_files:这是处理前端路由(如Vue Router的history模式)的灵魂配置。当Nginx找不到对应文件时,会返回index.html,由前端框架自己处理路由。
    • location /api/:将所有以/api开头的请求,转发给运行在127.0.0.1:8080的后端服务。proxy_set_header系列指令是为了将客户端的真实IP等信息传递给后端,否则后端日志里看到的全是127.0.0.1
  3. 测试配置并重载Nginx

    sudo nginx -t # 测试配置文件语法是否正确 sudo systemctl reload nginx # 重载配置,平滑重启,不影响已有连接

    现在,访问你的服务器公网IP或域名,应该能看到前端页面了,并且前端发起的API请求(如/api/user/login)也能被正确代理到后端。

5. 部署后的关键运维与安全加固

项目跑起来只是第一步,要让其稳定运行在公网,还必须进行一系列加固和优化。

5.1 配置HTTPS(SSL/TLS证书)

让网站使用HTTPS是当今的标配,它加密数据传输,防止被窃听或篡改,也是很多现代浏览器API的要求。我们可以从华为云或其他证书颁发机构(CA)申请免费的SSL证书(如Let‘s Encrypt)。这里以华为云提供的免费证书为例:

  1. 在华为云控制台搜索“SSL证书管理”,申请一张单域名免费证书(DigiCert签发),通常需要验证域名所有权(通过DNS解析添加一条TXT记录)。
  2. 证书审核签发后,下载证书文件(Nginx格式),你会得到两个文件:.key(私钥)和.crt(证书)。
  3. 将这两个文件上传到服务器的安全目录,例如/etc/nginx/ssl/
  4. 修改之前的Nginx配置,将80端口重定向到443,并配置SSL:
    server { listen 80; server_name your-domain.com www.your-domain.com; # 将HTTP请求永久重定向到HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name your-domain.com www.your-domain.com; # SSL证书路径 ssl_certificate /etc/nginx/ssl/your-domain.com.crt; ssl_certificate_key /etc/nginx/ssl/your-domain.com.key; # SSL优化配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 以下location配置与之前HTTP版本相同 location / { root /home/deploy/apps/your-project/frontend; index index.html index.htm; try_files $uri $uri/ /index.html; } 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; } }
  5. 再次测试并重载Nginx:sudo nginx -t && sudo systemctl reload nginx。现在用https://访问你的网站,浏览器地址栏应该会显示安全锁标志。

5.2 防火墙(Firewall)与安全组双重防护

我们之前配置了华为云的安全组,它相当于云平台层面的防火墙。在服务器内部,我们还应启用系统自带的防火墙(如firewalldufw),形成纵深防御。

对于CentOS (使用firewalld)

sudo systemctl start firewalld sudo systemctl enable firewalld # 放行SSH, HTTP, HTTPS端口(安全组已放行,这里再加一层) sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https # 重载防火墙规则 sudo firewall-cmd --reload # 查看已放行端口 sudo firewall-cmd --list-all

对于Ubuntu (使用ufw)

sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' # 同时放行80和443 sudo ufw enable # 启用防火墙,会中断现有SSH连接,请确保已放行SSH! sudo ufw status verbose

重要提醒:操作服务器防火墙时,务必确保当前SSH连接使用的端口(默认22)已被放行,否则启用防火墙的瞬间可能会被踢下线。

5.3 日志查看与进程监控

出问题时,日志是唯一的“黑匣子”。你需要知道去哪看日志。

  • Nginx访问日志与错误日志:默认在/var/log/nginx/目录下,分别是access.logerror.log。可以使用tail -f命令实时查看。
    sudo tail -f /var/log/nginx/error.log
  • Spring Boot应用日志:由于我们用了systemd管理,可以使用journalctl查看日志,或者如果你在application-prod.yml中配置了日志文件路径,就去对应路径查看。
    sudo journalctl -u your-app.service -f # -f 表示实时跟踪
  • 系统监控:使用htopglances工具可以直观查看CPU、内存、磁盘IO和网络使用情况。
    sudo yum install htop -y # CentOS sudo apt install htop -y # Ubuntu htop

5.4 自动化部署脚本初探

每次更新代码都手动上传、重启服务非常低效。可以编写一个简单的Shell脚本来自动化这个过程。在服务器上创建/home/deploy/scripts/deploy.sh

#!/bin/bash APP_NAME="your-app" BACKEND_DIR="/home/deploy/apps/your-project/backend" FRONTEND_DIR="/home/deploy/apps/your-project/frontend" echo "开始部署 $APP_NAME ..." # 1. 拉取最新代码(假设使用Git) # cd $FRONTEND_DIR && git pull origin main # cd $BACKEND_DIR && git pull origin main # 2. 构建(如果需要在服务器构建) # cd $BACKEND_DIR && mvn clean package -DskipTests # 前端构建可能更耗资源,建议在本地或CI/CD平台完成 # 3. 假设已经通过scp上传了新的Jar包和前端文件 # 这里执行重启后端服务的操作 sudo systemctl restart $APP_NAME # 4. 检查服务状态 sleep 5 sudo systemctl status $APP_NAME --no-pager echo "$APP_NAME 部署完成。"

给脚本执行权限:chmod +x /home/deploy/scripts/deploy.sh。以后部署时,只需要上传好文件,然后运行这个脚本即可。当然,更高级的做法是结合Git Webhook和Jenkins/GitHub Actions等CI/CD工具,实现提交代码后自动测试、构建、部署的全流程自动化。

走到这里,你的Web项目已经在一个相对安全、稳定的环境中运行起来了。从服务器选型、环境搭建、应用配置到安全加固,我们覆盖了一个标准部署流程的核心环节。这套流程和思路,不仅适用于华为云,也完全可以迁移到其他任何云平台或物理服务器。部署是一门实践的艺术,多操作几次,遇到并解决几个坑,你的经验就会越来越丰富。记住,备份和日志是你最好的朋友,任何重大操作前,做好快照或备份,遇到问题,第一时间查看日志。