2026.06.05

AI 开发实战-个人博客网站建设(四):项目部署

从零到一,使用AI工具开发,包含完整的后端服务、后台管理、博客网站,从项目创建到部署的整个流程。

项目搭建完成后,要想让别人访问,自然离不开部署工作。这里先简要介绍部署的过程,至于后续更深入的 CI/CD 等自动化部署操作,就留待以后再扩展完善了。这部分AI主要协助的是开发部署所需的配置文件。

准备工作

项目部署主要使用的是阿里云的相关产品,需要提前购买准备以下几项服务(购买的过程自行查阅):

  • ECS(云服务器):部署后端服务和运行环境的核心计算资源(Node项目购买时推荐选择Ubuntu系统)。
  • 域名:用户访问博客的网址,如 example.com(审批流程会比较久,没有也不影响正常部署访问)。
  • CDN(内容分发网络):用于加速网站静态资源的访问,提升用户加载速度(需要先有域名)。
  • SSL 证书:为域名配置 HTTPS 加密,保证数据传输安全(需要先有域名)。
  • OSS(对象存储服务):用于存放博客的静态文件,用法在后端服务篇有涉及(有域名后才可配置CDN与域名直接访问)。

服务器连接与软件安装

在有ECS后会让我们先重置一次密码,之后就可以连接服务器了,服务器可以通过下载XShell、Xftp软件进行连接操作,但也可以直接使用阿里云官方提供的远程连接功能进行访问。

Snipaste_2026-06-05_15-42-11

进入先执行更新命令,就可以开始安装所需的软件了

sudo apt update

nginx

sudo apt install nginx -y

node:这里使用nvm安装

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install 24

pm2

npm install -g pm2

mysql

sudo apt install mysql-server -y

启动连接mysql

启动

sudo systemctl start mysql

开机自启

sudo systemctl enable mysql

配置安全性

sudo mysql_secure_installation

按照提示设置 root 密码(推荐使用强密码),并回答以下问题:

  • Remove anonymous users? Y
  • Disallow root login remotely? Y
  • Remove test database and access to it? Y
  • Reload privilege tables now? Y

登录 MySQL(如果设置了 root 密码)

sudo mysql -u root -p

输入sql命令创建数据库

-- 创建数据库
CREATE DATABASE blogger CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 创建用户并授权
CREATE USER 'blogger_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';

-- 授予数据库权限
GRANT ALL PRIVILEGES ON blogger.* TO 'blogger_user'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

-- 退出 MySQL
EXIT;

允许远程连接(可以在外面访问到数据库):

image

运行

# 重启
sudo systemctl restart mysql

# 登录 MySQL
sudo mysql -u root -p

# 执行以下 SQL
-- 创建允许从任意IP访问的用户
CREATE USER 'blogger_user'@'%' IDENTIFIED BY 'StrongPassword123!';

-- 授予权限
GRANT ALL PRIVILEGES ON blogger.* TO 'blogger_user'@'%';

-- 刷新权限
FLUSH PRIVILEGES;

-- 退出
EXIT;

在ECS的安全组->管理规则->增加规则,注意这里设置0.0.0.0是不安全的,可以设置自己公网的ip/32

image (1)

之后我们就可以在自己电脑的mysql worksench访问数据库了 Snipaste_2026-06-05_15-56-20

后端服务部署

先拉取代码到我们的服务器上,这里以代码放在github上为例子,进行代码拉取:

  • 在ECS上生成SSH密钥:ssh-keygen -t rsa -b 4096 -C “your_email@example.com”
  • 获取ECS上的密钥:cat ~/.ssh/id_rsa.pub
  • 之后登录github-> Settings → SSH and GPG keys -> 添加ssh密钥添加进去
  • 回在ECS上克隆代码:
# 进入 opt 目录
cd /opt

# 克隆项目代码
git clone <您的项目仓库URL> blogger-server

# 更改项目所有权(有权限限制的话)
sudo chown -R $(whoami):$(whoami) blogger-server

# 进入项目目录
cd blogger-server

# 安装依赖
pnpm i

配置环境

# 创建环境文件
touch .env
NODE_ENV=production

DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=blogger_user
DB_PASSWORD=
DB_DATABASE=blogger

JWT_SECRET=

OSS_REGION=
OSS_BUCKET=
OSS_ACCESS_KEY_ID=
OSS_ACCESS_KEY_SECRET=

IMAGE_PROXY_BASE_URL=

初始化数据库

pnpm migration:run

启动

pm2 start ./dist/src/main.js --name="server"

pm2默认启动的是3000端口,此时如果想通过ECS的公共IP进行访问的话,依然需要在安全组中添加对应的端口,之后就可以正常使用公共的IP进行接口的调用。 image (1)

pm2配置文件

要完整的使用pm2功能,可以先在项目下添加ecosystem.config.js做为启动的配置文件,这里可以让AI生成下。

根据当前项目结构内容,在当前项目的根目录生成ecosystem.configjs的pm2配置文件,包含日志处理方式

生成后修改成需要的配置。

const fs = require('fs');
const path = require('path');

// 定位仓库根目录,确保从任意位置启动 PM2 都能找到正确路径。
const rootDir = __dirname;
// 将 PM2 日志放在项目内,方便统一收集和查看。
const logDir = path.join(rootDir, 'logs', 'pm2');

// 先创建日志目录,避免 PM2 打开日志文件时找不到路径。
fs.mkdirSync(logDir, { recursive: true });

module.exports = {
  apps: [
    {
      // 进程名称,会显示在 `pm2 list` 和日志输出中。
      name: 'blogger-server',
      // 强制从项目根目录解析文件路径。
      cwd: rootDir,
      // 生产环境入口文件,由 `pnpm run build` 生成。
      script: path.join(rootDir, 'dist', 'src', 'main.js'),

      // 以 cluster 模式运行,便于横向扩展。
      exec_mode: 'cluster',
      // 允许通过 `PM2_INSTANCES` 覆盖 worker 数量。
      instances: process.env.PM2_INSTANCES || 1,
      // 异常退出后自动重启进程。
      autorestart: true,
      // 生产环境关闭文件监听。
      watch: false,
      // 内存超过阈值时自动重启。
      max_memory_restart: process.env.PM2_MAX_MEMORY || '512M',
      // 增加重启延迟,避免快速重启循环。
      restart_delay: 3000,

      // PM2 正常启动时使用的默认运行变量。
      env: {
        // 保持运行行为与生产配置加载一致。
        NODE_ENV: 'production',
        // 如果外部没有传入端口,则使用默认端口。
        APP_PORT: process.env.APP_PORT || '3000',
      },
      // 使用 `pm2 start ecosystem.config.js --env production` 时读取的环境块。
      env_production: {
        // 显式锁定为生产模式。
        NODE_ENV: 'production',
        // 生产启动时保持相同的端口兜底值。
        APP_PORT: process.env.APP_PORT || '3000',
      },

      // pm2-logrotate 模块配置,用于控制 PM2 日志文件轮转策略。
      pm2_logrotate: {
        // 日志轮转的定时表达式,按 pm2-logrotate 的 cron 规则解析。
        rotateInterval: '0 0 * 3 * *',
        // 最多保留的历史轮转日志文件数量。
        retain: 10,
      },

      // 将普通标准输出写入独立日志文件。
      out_file: path.join(logDir, 'out.log'),
      // 将标准错误和崩溃日志写入独立文件。
      error_file: path.join(logDir, 'error.log'),
      // 合并所有 cluster worker 的日志到同一文件。
      merge_logs: true,
      // 在 PM2 控制台输出中显示时间戳。
      time: true,
      // 统一时间戳格式,方便排查生产日志。
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    },
  ],
};

之后提交代码,回到服务器的blogger-server文件夹下,重新拉取代码、运行。

# 拉取代码
git pull origin master

# 打包
pnpm build

# 关闭之前的服务
pm2 delete 0

# 使用配置文件启动新的pm2服务
pm2 start ecosystem.config.js

后台管理部署

后台管理部署这里不拉取代码了,直接将打包好的文件通过xftp上传至服务器内,使用nginx进行运行即可。

image (1)

配置nginx

找到配置地址:nginx -t image (1)

添加配置,并将其中api的访问做下代理,这样后台访问后端接口就直接访问了(后台的配置文件直接配置VITE_SERVICE_BASE_URL=/api)

server {
		listen 80;
		server_name 【ECS的公共IP地址,已经有域名的配置域名】;

		root /opt/blogger-admin;
		index index.html;

		location / {
			try_files $uri $uri/ /index.html;
		}
		location /api/ {
			proxy_pass http://127.0.0.1:3000;
			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;
		}
	}

启动

systemctl reload nginx

同样的需要在安全组中添加端口即可访问。 image (1)

前台博客部署

博客网站的部署类似后端服务的部署,也是使用pm2,所以这里可以先在项目下生成好pm2的配置文件,之后便是之前的步骤:

cd /opt

# 克隆项目代码
git clone <您的项目仓库URL> blogger-web

# 进入项目目录
cd blogger-web

# 安装依赖
npm i

# 打包
npm run build

# 启动
pm2 start ecosystem.config.js

添加好安全组后,博客也就正常访问了!

域名配置

在有域名了之后,可以先查看下官方文档,配置好域名解析。

博客主页

添加下nginx代理,代理至域名下,便可以直接通过域名访问到博客主页了。

server {
    listen 80;
    server_name www.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3004;
        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;
	}
}

重启nginx就可以访问博客了。

systemtrl restart nginx

后台管理

因为“www”已经被我们的博客占用了,那么我们需要去到阿里云的域名DNS云解析中配置新的主机记录,接着修改nginx:

server {
	listen 80;
	server_name new.yourdomain.com;

	root /opt/blogger-admin;
	index index.html;

	location / {
		try_files $uri $uri/ /index.html;
	}
	location /api/ {
		proxy_pass http://127.0.0.1:3000;
		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;
	}
}

再重启下,就可以使用该域名访问后台了。

SSL证书

要正常使用 HTTPS 访问,还需要申请 SSL 证书。在阿里云证书管理中可以申请免费的个人证书,有效期为 90 天。具体步骤如下:

  • 进入阿里云的证书管理控制台,选择“申请证书”。
  • 按表单要求填写域名及身份信息,提交申请。
  • 证书签发后,根据服务器类型选择 Nginx 格式的证书并下载。
  • 将下载的证书文件上传到服务器的 Nginx 目录下。
  • 在 Nginx 配置文件中添加对应的证书配置,启用 HTTPS。
server {
		listen 443 ssl; # 启用 SSL 并监听 443 端口
		server_name www.gujianruchu.cn;
		# 指定证书文件路径
		ssl_certificate gujianruchu.cn.pem;
		ssl_certificate_key gujianruchu.cn.key;
		# 配置 SSL 会话缓存,提高性能
		ssl_session_cache shared:SSL:1m;
		# 设置 SSL 会话超时时间
		ssl_session_timeout 5m;
		# 自定义设置使用的TLS协议的类型以及加密套件(以下为配置示例,请您自行评估是否需要配置)
		ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
		# 指定允许的 TLS 协议版本,TLS协议版本越高,HTTPS通信的安全性越高,但是相较于低版本TLS协议,高版本TLS协议对浏览器的兼容性较差
		ssl_protocols TLSv1.2 TLSv1.3;
		# 优先使用服务端指定的加密套件
		ssl_prefer_server_ciphers on;
		location / {
			proxy_pass http://127.0.0.1:3004;
			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;
		}
	}
	server {
		listen 80;
		server_name www.gujianruchu.cn;
		# 将 HTTP 请求重定向到 HTTPS
		return 301 https://$host$request_uri;
	}

配置后就可以正常使用https访问博客了。

而由于使用的是个人的测试证书,该证书仅能支持单域名,后台管理端要使用就得再去重新申请新证书,使用后台的域名进行申请后,同样按照博客的添加方式添加,之后也就可以使用https访问后台了。

OSS域名配置

当前博客的图片访问仍通过 API 转发实现,有了域名后,便可通过在 OSS 中配置域名直接访问。具体配置步骤如下:

  1. 添加域名解析:前往阿里云域名 DNS 云解析,新增一条解析记录,记录类型为 CNAME,记录值填写外网访问的 OSS Bucket 域名。

  2. 申请并绑定证书:图片域名也需要 HTTPS 访问,因此需要为该域名申请 SSL 证书。证书申请完成后,进入 OSS 控制台的 Bucket 配置 → 域名管理,添加域名并绑定证书。

  3. 开启公共读权限:此时通过“域名 + 图片存储路径”直接访问图片可能会返回 403。需要进入 OSS 的 权限管理 → 读写权限,将“阻止公共访问”与“读写权限”都设置为公共读,图片即可正常访问。

  4. 设置防盗链:公共读意味着任何人可以直接请求图片资源。为了安全,建议在 数据安全 → 防盗链 中开启防盗链,将允许访问的域名(如博客主域名)添加至白名单,限制仅指定域名可以请求图片。

CDN加速

参考通过CDN加速访问OSS配置,修改原先DNS云解析中的图片主机记录,将记录值修改指向CDN提供的加速地址。之后便可使用CDN的加速加载资源了,当然为了安全起见,最好配置下一些访问限制,以防盗刷产生不必要的费用。

Snipaste_2026-06-06_16-48-43

公安联网备案

网站上线后,需要安照要求进行公安联网备案,有关内容这里就不过多描述了,可以在阿里云上搜索文档进行操作。

ICP备案后处理