说明:
- 本文面向无 Docker、无数据库、无运维经验的读者
- 文章里的域名统一使用
your-domain.com- 文章里的公网 IP 统一使用
<服务器公网IP>- 服务端、运营后台、品牌官网都使用通用名称,不暴露真实项目名
- 文章默认部署的是一套三站点系统:品牌官网、运营后台、内容服务端
1. 先把整件事讲清楚
这篇文章要解决的,不是“怎么写代码”,而是“怎么把一套已经写好的系统,真正放到阿里云服务器上,让别人能访问”。
对一个没有运维经验的人来说,最容易混淆的其实就四件事:
- 服务器:代码最终运行的地方
- 域名:用户在浏览器里输入的地址
- DNS 解析:把域名指向服务器
Nginx:把不同域名转发到不同程序,或者直接把静态页面发给浏览器
你可以先记住一个最简单的分工:
your-domain.com:品牌官网admin.your-domain.com:运营后台api.your-domain.com:内容服务端
服务器上再分成三层:
Nginx负责对外接收访问PM2负责管理 Node.js 服务端进程MySQL负责保存数据
如果把这三层分清楚,后面你会发现部署并没有想象中复杂。
2. 第一步:购买阿里云 ECS 服务器
如果你还没有服务器,先买一台 ECS。对于刚开始做部署的人,不建议一上来就买太大,也不建议买得太小。
2.1 推荐怎么选
| 项目 | 建议 |
|---|---|
| 计费方式 | 包年包月优先,按量付费适合临时测试 |
| 地域 | 选离目标用户近的地域 |
| 实例规格 | 起步可用 2 vCPU + 4 GiB |
| 系统盘 | 建议 80 GiB 起步 |
| 公网带宽 | 前期 3 Mbps 基本够用 |
| 操作系统 | Alibaba Cloud Linux 3 或 Ubuntu 22.04 |
2.2 买完后先放行端口
服务器买好后,不要急着装软件,先把安全组设置好。最少放行这些端口:
| 端口 | 用途 | 来源建议 |
|---|---|---|
22 | SSH 登录 | 0.0.0.0/0 |
80 | HTTP 访问 | 0.0.0.0/0 |
443 | HTTPS 访问 | 0.0.0.0/0 |
3000 | Node 服务端本机监听 | 仅本机 |
3306 | MySQL 本机监听 | 仅本机 |
注意:
3000和3306不要直接暴露给公网- 真正对外只保留
80/443
3. 第二步:购买域名并完成实名
如果你还没有域名,先去阿里云域名控制台买一个。
3.1 域名建议
为了后面方便区分,建议直接准备这些域名:
your-domain.comwww.your-domain.comadmin.your-domain.comapi.your-domain.com
如果你暂时只想做最小版本,也可以先买主域名,后面再补子域名。
3.2 购买和实名步骤
- 打开阿里云域名控制台
- 搜索你要的域名
- 确认可注册后下单
- 完成实名信息提交
- 等待审核通过
域名审核没通过之前,后面的 DNS 解析、HTTPS 证书申请都没法真正落地,所以这一步要先做完。
4. 第三步:登录服务器
服务器买好后,第一件事不是装 Node,也不是配 Nginx,而是先能稳定登录进去。
4.1 先准备这四样东西
你在登录前至少要确认:
- 服务器公网 IP
- 登录用户名
- 购买服务器时设置的密码
- 安全组已经放行
22端口
如果这四样缺一项,SSH 基本都会失败。
4.1.1 如何查看服务器公网 IP
登录阿里云 ECS 控制台后,进入实例列表,找到你的服务器,在信息栏里可以直接看到:
公网 IP私网 IP
这里我们要用的是 公网 IP,不要把私网 IP 拿去做外网访问。
你后面所有需要填写地址的地方,优先都用这个公网 IP 作为临时排障入口。
4.2 先用 Workbench 验证
如果你是第一次登录服务器,或者本机 SSH 一直连不上,先用阿里云控制台的 Workbench。
步骤如下:
- 打开 ECS 控制台
- 进入实例列表
- 找到目标服务器
- 点击远程连接
- 选择
Workbench 远程连接 - 输入用户名和密码登录
如果 Workbench 能进,说明服务器本身是正常的,问题大概率只在你本机 SSH 工具或密码设置上。
4.3 Windows 下用 Xshell 登录
如果你用的是 Windows,最省心的方式是 Xshell。
连接信息填写如下:
| 项目 | 内容 |
|---|---|
| 主机 | <服务器公网IP> |
| 协议 | SSH |
| 端口 | 22 |
| 用户名 | root |
连接成功后,通常会看到类似:
root@server:~#
4.4 Windows 下直接用 PowerShell 登录
如果你不想装 Xshell,也可以直接在 PowerShell 里执行:
ssh root@<服务器公网IP>
第一次连接时会提示确认指纹,输入 yes 即可。然后输入 root 密码。
4.5 macOS 下用终端登录
macOS 直接打开终端执行:
ssh root@<服务器公网IP>
4.6 如果 SSH 连不上,先查这几项
- 服务器是否处于运行中
- 安全组是否放行了
22 - 你输入的是不是公网 IP,而不是私网 IP
- 服务器系统是否默认禁用了 root 密码登录
如果要临时开启密码登录,可以在服务器上执行:
vi /etc/ssh/sshd_config
把这两项改成:
PasswordAuthentication yes
PermitRootLogin yes
如果前面有 #,一起去掉。
保存后重启 SSH:
# Ubuntu
systemctl restart ssh
# CentOS / Alibaba Cloud Linux
systemctl restart sshd
5. 第四步:安装基础环境
登录成功后,开始装基础软件。你可以把这一段理解成“服务器开工前的工具箱准备”。
5.1 先确认系统类型
cat /etc/os-release
如果看到的是 Ubuntu,后面优先用 apt。
如果看到的是 Alibaba Cloud Linux / CentOS / RHEL,后面优先用 dnf。
5.2 安装 Git
Git 用来拉代码和更新代码。
Ubuntu / Debian:
apt update
apt install -y git
git --version
Alibaba Cloud Linux / CentOS / RHEL:
dnf update -y
dnf install git -y
git --version
5.3 安装 nano
nano 是一个适合新手的命令行编辑器,后面你会经常用它来新建和修改 .env、nginx 配置文件。
Ubuntu / Debian:
apt install -y nano
nano --version
Alibaba Cloud Linux / CentOS / RHEL:
dnf install nano -y
nano --version
安装完成后,最常用的命令就是:
nano .env
5.4 安装 Node.js
服务端是 Node.js 项目,所以这一步必须做。
Ubuntu / Debian:
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
node -v
npm -v
Alibaba Cloud Linux / CentOS / RHEL:
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
dnf install nodejs -y
node -v
npm -v
建议看到 v20.x.x 再往下走。
5.5 安装 MySQL
Ubuntu / Debian:
apt install -y mysql-server
systemctl status mysql
Alibaba Cloud Linux / CentOS / RHEL:
dnf install mysql-server -y
systemctl start mysqld
systemctl enable mysqld
systemctl status mysqld
如果看到 active (running),说明 MySQL 已经正常起来了。
5.5.1 修改 MySQL root 密码
MySQL 装好以后,建议第一时间把 root 密码改成你自己设的密码,后面创建数据库和写 .env 都会用到。
先登录 MySQL:
# Ubuntu / Debian 有些机器会走 socket 认证,可以先试这个
sudo mysql
# 如果已经配置了密码,也可以继续用这个
mysql -u root -p
进入 mysql> 以后执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
FLUSH PRIVILEGES;
EXIT;
改完以后,再重新登录一次确认密码已经生效:
mysql -u root -p
如果你的新密码里包含 @、#、! 之类的特殊字符,后面写进 DATABASE_URL 时要注意做 URL 编码,别直接原样拼进去。
5.6 安装 PM2
PM2 用来守护 Node 服务,避免进程挂掉后就没了。
npm install -g pm2
pm2 -v
5.7 安装 Nginx
Nginx 用来做站点入口和反向代理。
Ubuntu / Debian:
apt install -y nginx
systemctl start nginx
systemctl enable nginx
systemctl status nginx
Alibaba Cloud Linux / CentOS / RHEL:
dnf install nginx -y
systemctl start nginx
systemctl enable nginx
systemctl status nginx
6. 第五步:准备数据库
如果一台服务器同时跑内容服务端和运营后台,数据库最好先拆清楚。
6.1 先登录 MySQL
mysql -u root -p
如果提示输入密码时,直接按回车,有可能就能以“空密码”进入。
进入后会看到类似:
Welcome to the MySQL monitor.
mysql>
如果空密码进不去,再去 systemd 日志里找密码线索:
journalctl -u mysqld --no-pager | grep -i password
journalctl -u mysqld --no-pager | tail -n 100
5.2 修改 root 密码并创建数据库
# 登录 MySQL(初始无密码,直接回车)
mysql -u root
进去后依次执行以下 SQL 命令(逐行复制执行):
-- 修改 root 密码(把 YourPassword123! 换成你自己的密码,务必改掉)
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPassword123!';
-- 创建项目数据库
CREATE DATABASE app_main CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 刷新权限
FLUSH PRIVILEGES;
-- 显示数据库列表
SHOW DATABASES;
-- 退出
EXIT;
⚠️ 记下你设置的密码,后面配置 .env 文件时要用。
6.3 新手要记住的点
- 一个系统尽量对应一个数据库
- 服务端和后台不要长期共用同一个库
- 后面
.env里的DATABASE_URL必须和这里的库名对应 - 如果密码里带特殊字符,连接串要做编码
6.4 MySQL 交互界面的新手注意事项
很多新手第一次进入 mysql> 后,最容易犯的不是命令错,而是“交互方式没适应”。
先记住这几条:
- 每条 SQL 语句末尾都要加分号
; mysql>里输入不完整时,回车后不会立刻执行- 语句写错后,不要慌,先补完再执行
- 退出命令是
EXIT; - 在 MySQL 交互界面里,命令和普通 shell 命令不是一回事
例如下面这样才算完整:
CREATE DATABASE app_main DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
如果你忘了分号,MySQL 会继续等你输入下一行,不会立刻报错。
6.5 如果后面需要重新修改 MySQL 密码
如果你已经知道当前 root 密码,最简单的做法是先登录:
mysql -u root -p
进入 mysql> 后执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
FLUSH PRIVILEGES;
EXIT;
然后重新验证:
mysql -u root -p
输入新密码,能正常进入就说明修改成功。
如果你当前还停留在 mysql> 交互界面里,也可以不退出,直接执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
FLUSH PRIVILEGES;
如果密码里有特殊字符,记得做 URL 编码。例如:
Icd@admin
应写成:
Icd%40admin
6.5 如何验证数据库是否真的建好了
mysql -u root -p -e "SHOW DATABASES;"
如果你能看到刚刚创建的库名,说明数据库已经准备成功。
7. 第六步:准备服务器目录
目录先规划好,后面才不会乱。
mkdir -p /opt/app/workspace/service
mkdir -p /opt/app/workspace/admin
mkdir -p /opt/www/official
mkdir -p /opt/logs/service
mkdir -p /opt/logs/nginx
mkdir -p /opt/backup/mysql
推荐你这样理解:
/opt/app/workspace/service放内容服务端源码/opt/app/workspace/admin放运营后台源码或构建产物/opt/www/official放品牌官网静态文件
8. 第七步:部署内容服务端
这部分是整篇文章的核心。你可以把它理解成“把代码变成一个能长期跑的服务”。
8.1 拉取代码
如果你已经能从 Git 仓库拉代码,直接执行:
cd /opt/app/workspace/service
git clone <你的服务端仓库地址> .
如果你是手动上传压缩包,也可以先传到服务器,再解压到这个目录。
8.2 配置服务端 .env
服务端最关键的配置文件就是 .env。它决定了服务端连哪个数据库、监听哪个端口、允许哪个后台访问。
NODE_ENV=production
PORT=3000
APP_NAME=service-api
DATABASE_URL=mysql://root:<数据库密码>@127.0.0.1:3306/app_main
JWT_SECRET=<服务端独立密钥>
JWT_REFRESH_SECRET=<刷新密钥>
APP_SECRET=<应用密钥>
CORS_ORIGINS=https://admin.your-domain.com
UPLOAD_BASE_URL=https://api.your-domain.com/uploads
你可以先理解这几个字段:
PORT:服务端自己监听的本机端口DATABASE_URL:服务端连接 MySQL 的地址CORS_ORIGINS:允许哪个后台网页访问接口UPLOAD_BASE_URL:上传后的文件对外访问地址
8.2.1 如何用 nano 新建和修改文件
你后面会经常改 .env、nginx 配置文件,所以这里顺手把 nano 的基本用法补齐。
打开文件
nano .env
如果文件不存在,nano 会直接帮你新建。
修改内容
打开后直接输入、粘贴即可,nano 没有复杂模式。
保存并退出
按下面顺序操作:
Ctrl + X- 输入
Y - 按
Enter
只想退出不保存
Ctrl + X- 输入
N
新手最容易卡住的地方
- 复制完内容后忘了保存
- 以为
Ctrl + X就是退出,结果其实没写入文件 - 文件路径写错了,编辑的是另一个同名文件
如果你不习惯 nano,也可以用 vi,但对新手来说 nano 更直观。
8.3 安装依赖并构建
进入服务端目录后,按顺序执行:
npm install
npm run prisma:generate
npx prisma migrate deploy
npm run build
这几步分别对应:
- 安装第三方依赖
- 生成 Prisma 代码
- 执行数据库迁移
- 编译 TypeScript 代码
建议你执行完后看一下构建产物:
ls -la dist
8.4 用 PM2 启动服务端
构建成功后,再让 PM2 接管进程:
pm2 start dist/src/server.js --name service-api
pm2 save
pm2 startup
如果你是第一次接触 PM2,可以把它理解成“服务端守护工具”。它会负责:
- 服务挂了自动拉起
- 服务器重启后自动启动
- 统一查看日志
8.5 验证服务端
pm2 status
pm2 logs service-api --lines 50
curl http://127.0.0.1:3000/health
如果 health 能返回正常 JSON,说明内容服务端已经起来了。
8.6 服务端更新时怎么做
后续只要代码更新,通常就是:
cd /opt/app/workspace/service
git pull
npm install
npm run build
pm2 restart service-api
如果改了数据库结构,还要补执行迁移:
npx prisma migrate deploy
9. 第八步:部署运营后台
运营后台不是 Node 服务,通常是一个静态前端站点。它的流程和服务端不一样。
9.1 先配置后台接口地址
后台构建前,先把接口地址写对:
VITE_BASE_API=https://api.your-domain.com
这一步很关键。后台页面最终会把接口请求打到这个地址上。
9.2 构建后台
进入后台项目目录,执行:
cd /opt/app/workspace/admin
npm install
npm run build
9.3 检查构建产物
构建完成后,确认有没有 dist 目录:
ls -la dist
正常情况下至少会看到:
index.htmlassets/
9.4 放到静态目录
把构建产物复制到静态目录:
cp -r dist/* /opt/www/admin/
如果是官网,就放到 /opt/www/official/。
10. 第九步:部署品牌官网
官网如果只是展示页,最简单的方式就是纯静态站。
10.1 官网目录
cp -r <官网静态文件>/* /opt/www/official/
10.2 官网至少要有什么
- 首页
- 产品介绍
- 下载引导
- 合规信息
- 联系方式或备案信息入口
如果你现在还没有完整页面,先把首页和下载入口做出来,至少保证能访问。
11. 第十步:配置域名解析
这一步是“域名绑定”的核心。
11.1 解析记录怎么配
在域名解析控制台里,建议添加这些记录:
| 主机记录 | 记录类型 | 记录值 |
|---|---|---|
@ | A | <服务器公网IP> |
www | A | <服务器公网IP> |
admin | A | <服务器公网IP> |
api | A | <服务器公网IP> |
如果你只想保留主域名入口,也可以让 www 统一跳转到主域名。
11.2 先确认 DNS 生效
nslookup your-domain.com
nslookup www.your-domain.com
nslookup admin.your-domain.com
nslookup api.your-domain.com
如果解析结果没有指向你的服务器公网 IP,就先不要继续下一步。
11.3 如何把公网 IP 和域名绑定起来
这一步其实就是给域名加解析记录。你可以把它理解成:
- 域名负责“叫什么”
- 公网 IP 负责“指向哪台机器”
- DNS 负责把这两者连起来
操作时,在域名解析控制台里添加这些记录:
| 主机记录 | 记录类型 | 记录值 |
|---|---|---|
@ | A | <服务器公网IP> |
www | A | <服务器公网IP> |
admin | A | <服务器公网IP> |
api | A | <服务器公网IP> |
如果你刚买完域名,通常就是:
- 先填
@ - 再填
www - 然后填
admin - 再填
api
保存后等待解析生效。通常几分钟到半小时不等。
12. 第十一步:配置 Nginx 站点绑定
Nginx 的作用,就是把不同域名接到不同目录或不同服务上。
12.1 官网
server {
listen 80;
server_name your-domain.com www.your-domain.com;
root /opt/www/official;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
12.2 运营后台
server {
listen 80;
server_name admin.your-domain.com;
root /opt/www/admin;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
12.3 内容服务端
server {
listen 80;
server_name api.your-domain.com;
client_max_body_size 20m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
}
12.4 检查并重载
nginx -t
systemctl reload nginx
systemctl status nginx
如果你是 Alibaba Cloud Linux / CentOS / RHEL,通常把配置放在 /etc/nginx/conf.d/ 就可以了。
13. 第十二步:申请 HTTPS 证书
现在正式站点基本都应该上 HTTPS。最简单的方式是 Let's Encrypt + certbot。
13.1 安装 certbot
dnf install certbot python3-certbot-nginx -y
如果是 Ubuntu:
apt install -y certbot python3-certbot-nginx
13.2 申请证书
certbot --nginx -d your-domain.com -d www.your-domain.com
certbot --nginx -d admin.your-domain.com
certbot --nginx -d api.your-domain.com
13.3 验证自动续期
certbot renew --dry-run
只要这一步通过,说明后面证书自动续期已经有保障了。
14. 第十三步:切换到 HTTPS
证书申请成功后,把 80 端口改成跳转,443 端口改成正式访问。
官网示例:
server {
listen 80;
server_name your-domain.com www.your-domain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
root /opt/www/official;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
后台和服务端同理,只是 server_name 和证书路径不同。
15. 第十四步:最终验收
不要只看首页能不能打开,最好按下面顺序检查:
pm2 status
pm2 logs service-api --lines 50
systemctl status mysqld
systemctl status nginx
curl http://127.0.0.1:3000/health
curl -I https://your-domain.com
curl -I https://admin.your-domain.com
curl -I https://api.your-domain.com/health
certbot renew --dry-run
浏览器里再打开:
https://your-domain.comhttps://admin.your-domain.com/loginhttps://api.your-domain.com/health
如果这三项都正常,说明整套三站点基本已经落地。
16. 常见问题
16.1 apt 提示 command not found
这通常说明你不是 Ubuntu 系统,而是 Alibaba Cloud Linux / CentOS / RHEL。这类系统改用 dnf。
16.2 .env 明明改了,但服务没生效
原因一般不是文件没保存,而是进程没重启。
pm2 restart service-api
16.3 后台打开是空白页或 404
优先检查两点:
- 有没有执行
npm run build Nginx root指向的是不是dist
16.4 访问后台时报 Network Error
这通常说明后台构建产物里的接口地址不对。优先检查 VITE_BASE_API。
16.5 服务端 502 Bad Gateway
优先检查:
PM2进程是否存在- 服务端端口是否真的是
3000 proxy_pass指向的本地端口是否一致
16.6 官网访问正常,但 www 不正常
常见原因是:
www没做解析server_name没写www- 证书没覆盖
www - 官网静态目录里没有首页文件
17. 结语
一套阿里云 ECS 上的三站点部署,真正要做的不是“把代码传上去”,而是把下面这几件事都收口清楚:
- 服务器怎么买
- 域名怎么买、怎么实名
- 域名怎么解析到服务器
- 服务器怎么登录
Node.js、MySQL、Git怎么装- 服务端怎么构建、怎么用
PM2托管 - 运营后台怎么构建、怎么交给
Nginx - 官网怎么放静态目录
- HTTPS 怎么申请、怎么验证