AI掘金头条项目部署实践指南

项目部署文档 - Red Hat Enterprise Linux 10.1 虚拟机部署

项目概述

本项目包含两个部分:

  • 前端: Vue 3 + Vite + Vant 移动端新闻应用 (端口: 5173)
  • 后端: FastAPI + MySQL 新闻API服务 (端口: 8000)

一、环境准备

1.1 系统配置

项目 最低配置 推荐配置
CPU 2核 4核
内存 4GB 8GB
磁盘 40GB 80GB
操作系统 Red Hat Enterprise Linux 10.1 RHEL 10.1

1.3 安装基础软件

bash 复制代码
# 安装基础依赖 (Python 3.12 已预装)
sudo dnf install -y python3-pip git curl unzip nginx redis

1.4 创建项目用户

bash 复制代码
sudo useradd -m -s /bin/bash deploy
sudo mkdir -p /root/xwzx-news
sudo chown -R deploy:deploy /root/xwzx-news

1.5 关闭 SELinux 和配置 Firewalld (可选)

bash 复制代码
# 临时关闭 SELinux (生产环境建议配置策略)
sudo setenforce 0

# 永久关闭 (需重启)
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

# 配置防火墙
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --reload

二、数据库安装与配置 (MySQL 8.4.8)

2.1 安装 MySQL 8.4.8 (RHEL 10 官方仓库)

RHEL 10 默认仓库没有 mysql-server,需要添加 MySQL 官方 YUM 仓库:

bash 复制代码
# 1. 下载 MySQL 8.4.8 Yum 仓库 RPM 包
dnf install -y https://dev.mysql.com/get/mysql84-community-release-el10-2.noarch.rpm

# 2. 安装 MySQL 8.4.8
yum install mysql-community-server -y

# 3. 启动并设置开机启动
sudo systemctl start mysqld
sudo systemctl enable mysqld

# 4. 获取临时密码 (首次安装会生成临时密码)
sudo grep 'temporary password' /var/log/mysqld.log

# 5. 登录mysql
mysql -uroot -p".+ky6+LEL<qv"

# 6. 更改root默认密码
alter user 'root'@'localhost' identified by 'MySQL@123';

2.2 导入数据库表结构

bash 复制代码
# 把前后端的项目代码源文件上传到服务器
[root@localhost ~]# ll
total 208
-rw-------.  1 root root    752 Apr 18 15:36 anaconda-ks.cfg
-rw-r--r--.  1 root root 208012 May  2 16:17 database.sql
drwxr-xr-x. 12 root root    184 May  2 16:05 toutiao_backend
drwxr-xr-x.  5 root root    136 May  2 16:06 xwzx-news

# 导入数据库 (先创建数据库用户)
mysql -uroot -p'MySQL@123' -e "CREATE DATABASE IF NOT EXISTS news_app CHARACTER SET utf8mb4;"

# 导入表结构和数据
mysql -uroot -p'MySQL@123' news_app < database.sql

2.3 数据库表说明

导入的表结构:

  • user - 用户信息表
  • user_token - 用户令牌表
  • news_category - 新闻分类表
  • news - 新闻表
  • related_news - 相关新闻关联表
  • favorite - 收藏表
  • history - 浏览历史表

三、缓存服务 (Redis)

3.1 安装 Redis (源码编译)

Redis 不在 RHEL 10 默认仓库中,采用源码编译安装:

bash 复制代码
# 1. 安装编译依赖
sudo dnf install -y gcc make

# 2. 下载 Redis 7.4.2 源码,直接去浏览器下载,然后上传
https://github.com/redis/redis/archive/refs/tags/7.4.2.tar.gz

# 3. 编译安装
tar xzf redis-7.4.2.tar.gz
cd redis-7.4.2
make -j$(nproc)
sudo make install

# 4. 创建配置目录并复制配置文件
sudo mkdir -p /etc/redis
sudo cp redis.conf /etc/redis/

# 5. 修改配置以守护进程运行
sudo sed -i 's/^daemonize no/daemonize yes/' /etc/redis/redis.conf
sudo sed -i 's/^bind 127.0.0.1/bind 0.0.0/' /etc/redis/redis.conf

3.2 启动 Redis

bash 复制代码
# 直接运行 Redis 服务器
/usr/local/bin/redis-server /etc/redis/redis.conf

# 验证
redis-cli ping
# 应返回: PONG

四、后端部署 (FastAPI)

4.1 安装 Python 虚拟环境依赖

bash 复制代码
# 进入后端目录
cd toutiao_backend/

# 创建虚拟环境 (RHEL 10 使用 python3)
python3 -m venv venv

# 激活虚拟环境
source venv/bin/activate

# 安装依赖
pip install fastapi uvicorn sqlalchemy aiomysql python-jose passlib==1.7.4 python-multipart pydantic pydantic-settings bcrypt==3.2.2 redis

4.2 修改数据库配置

编辑 config/db_config.py,修改数据库连接信息:

python 复制代码
# 数据库URL - 使用 localhost,如果密码包含特殊字符需要 URL 编码
# 例如 @ 编码为 %40
ASYNC_DATABASE_URL = "mysql+aiomysql://root:MySQL%40123@localhost:3306/news_app?charset=utf8mb4"

注意:如果 MySQL 允许远程连接,可以使用服务器 IP,但需确保 MySQL 用户有对应主机的权限。

4.3 使用 systemd 管理后端服务

bash 复制代码
# 创建 systemd 服务文件
sudo cat > /etc/systemd/system/xwzx-news-backend.service << 'EOF'
[Unit]
Description=XWZX News API Backend
After=network.target mysqld.service

[Service]
User=root
Group=root
WorkingDirectory=/root/toutiao_backend
ExecStart=/root/toutiao_backend/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
Restart=always
RestartSec=5
Environment="PYTHONPATH=/root/toutiao_backend"

[Install]
WantedBy=multi-user.target
EOF

# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start xwzx-news-backend

# 设置开机启动
sudo systemctl enable xwzx-news-backend

# 查看服务状态
sudo systemctl status xwzx-news-backend

4.4 验证后端服务

bash 复制代码
# 检查服务状态
sudo systemctl status xwzx-news-backend

# 测试 API
curl http://localhost:8000/
# 应返回: {"message":"Hello World"}

五、前端部署 (Vue + Vite)

5.1 安装 Node.js (RHEL 10)

bash 复制代码
# 使用 NodeSource 仓库安装 Node.js 20 LTS
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs

5.2 前端 API 配置

修改 src/config/api.js必须使用空字符串

javascript 复制代码
// API基础URL配置 - 必须为空字符串
export const apiConfig = {
  baseURL: ''
}

注意baseURL 不能为 /,否则拼接后变成 //api/user/register 被浏览器当成协议相对 URL,导致请求失败。

5.3 构建前端

bash 复制代码
cd /root/xwzx-news

# 安装依赖
npm install

# 构建生产版本
npm run build

# 复制到 Nginx 目录
sudo rm -rf /usr/share/nginx/html/xwzx-news
sudo cp -r /root/xwzx-news/dist /usr/share/nginx/html/xwzx-news

# 启动 Nginx
sudo systemctl start nginx
sudo systemctl enable nginx

5.4 nginx反向代理配置

bash 复制代码
[root@localhost ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
        listen       80;
        server_name  _;

        root /usr/share/nginx/html/xwzx-news;
        index index.html;

        location / {
            try_files $uri $uri/ /index.html;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

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

六、部署检查清单

6.1 服务启动顺序

bash 复制代码
# 1. 确保 MySQL 运行
sudo systemctl status mysqld

# 2. 启动 Redis
/usr/local/bin/redis-server /etc/redis/redis.conf

# 3. 启动后端 API
sudo systemctl start xwzx-news-backend

# 4. 检查后端是否正常
curl http://localhost:8000/

# 5. 确保 Nginx 运行
sudo systemctl status nginx

6.2 常见问题排查

问题 解决方法
后端无法连接数据库 检查 MySQL 服务状态 (sudo systemctl status mysqld) 和密码配置
前端 API 请求失败 检查 api.js 中的 baseURL 配置
502 Bad Gateway Nginx 无法连接后端,检查后端服务是否运行
静态资源加载失败 检查 Nginx root 路径是否正确
SELinux 拒绝访问 执行 sudo setenforce 0 临时关闭,或配置正确的安全上下文

6.3 日志查看

bash 复制代码
# 后端日志
sudo journalctl -u xwzx-news-backend -f

# MySQL 日志
sudo journalctl -u mysqld -f
sudo tail -f /var/log/mysqld.log

# Nginx 日志
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log

七、安全配置 (生产环境必做)

7.1 修改数据库密码

编辑 config/db_config.py 使用强密码

7.2 配置 CORS

编辑 main.py,将 allow_origins=["*"] 改为具体的前端域名:

python 复制代码
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://your-domain.com"],  # 只允许指定域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

7.3 配置 Firewalld (RHEL 10)

bash 复制代码
# 只开放必要端口
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

7.4 SELinux 配置 (RHEL 10 推荐)

建议不要完全关闭 SELinux,而是配置正确的安全上下文:

bash 复制代码
# 允许 Nginx 访问网络
sudo setsebool -P httpd_can_network_connect 1

# 允许 Nginx 访问后端端口
sudo setsebool -P nhttpd_can_network_connect 1

# 如果需要访问特定目录
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/root/xwzx-news(/.*)?"
sudo restorecon -R /root/xwzx-news

八、快速部署脚本 (RHEL 10)

将以下脚本保存为 deploy.sh 并执行:

bash 复制代码
#!/bin/bash
set -e

PROJECT_DIR="/root"
DB_NAME="news_app"
DB_ROOT_PASS="MySQL@123"
REDIS_VER="7.4.2"

echo "=== XWZX News 部署脚本 (RHEL 10) ==="

# 1. 安装系统依赖
echo "[1/9] 安装系统依赖..."
sudo dnf install -y python3-pip git curl unzip nginx gcc make

# 2. 安装 MySQL 8.4.8
echo "[2/9] 安装 MySQL 8.4.8..."
curl -fsSL https://dev.mysql.com/get/mysql84-community-release-el10-2.noarch.rpm -o mysql84-community.rpm
sudo dnf install -y mysql84-community.rpm
sudo dnf install -y mysql-community-server
sudo systemctl start mysqld
sudo systemctl enable mysqld

# 3. 配置 MySQL
echo "[3/9] 配置 MySQL..."
echo "等待 MySQL 启动..."
until mysql -e "SELECT 1" &>/dev/null; do
    sleep 2
done
sudo mysql -e "CREATE DATABASE IF NOT EXISTS ${DB_NAME} CHARACTER SET utf8mb4;"
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASS}';"

# 4. 导入数据库
echo "[4/9] 导入数据库..."
mysql -uroot -p"${DB_ROOT_PASS}" ${DB_NAME} < /root/database.sql

# 5. 安装 Redis (源码编译)
echo "[5/9] 安装 Redis..."
cd /tmp
curl -fsSL https://github.com/redis/redis/archive/refs/tags/${REDIS_VER}.tar.gz -o redis-${REDIS_VER}.tar.gz
tar xzf redis-${REDIS_VER}.tar.gz
cd redis-${REDIS_VER}
make -j$(nproc)
sudo make install
sudo mkdir -p /etc/redis
sudo cp redis.conf /etc/redis/
sudo sed -i 's/^daemonize no/daemonize yes/' /etc/redis/redis.conf
sudo sed -i 's/^bind 127.0.0.1/bind 0.0.0/' /etc/redis/redis.conf
/usr/local/bin/redis-server /etc/redis/redis.conf

# 6. 创建 Python 虚拟环境
echo "[6/9] 创建 Python 虚拟环境..."
cd ${PROJECT_DIR}/toutiao_backend
python3 -m venv venv

# 创建 requirements.txt
cat > requirements.txt << 'EOF'
fastapi==0.115.0
uvicorn[standard]==0.30.6
sqlalchemy==2.0.35
aiomysql==0.2.0
python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4
python-multipart==0.0.12
pydantic==2.9.2
pydantic-settings==2.5.2
bcrypt==3.2.2
redis
EOF

${PROJECT_DIR}/toutiao_backend/venv/bin/pip install -r ${PROJECT_DIR}/toutiao_backend/requirements.txt

# 7. 创建 systemd 服务
echo "[7/9] 创建后端服务..."
sudo cat > /etc/systemd/system/xwzx-news-backend.service << 'EOF'
[Unit]
Description=XWZX News API Backend
After=network.target mysqld.service

[Service]
User=root
Group=root
WorkingDirectory=/root/toutiao_backend
ExecStart=/root/toutiao_backend/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
Restart=always
RestartSec=5
Environment="PYTHONPATH=/root/toutiao_backend"

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable xwzx-news-backend
sudo systemctl start xwzx-news-backend

# 8. 安装 Node.js 并构建前端
echo "[8/9] 构建前端..."
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
cd ${PROJECT_DIR}/xwzx-news
npm install
npm run build
sudo rm -rf /usr/share/nginx/html/xwzx-news
sudo cp -r ${PROJECT_DIR}/xwzx-news/dist /usr/share/nginx/html/xwzx-news

# 9. 配置 Nginx
echo "[9/9] 配置 Nginx..."
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo cat > /etc/nginx/nginx.conf << 'NGINXCONF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
        listen       80;
        server_name  _;

        root /usr/share/nginx/html/xwzx-news;
        index index.html;

        location / {
            try_files $uri $uri/ /index.html;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

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

sudo systemctl enable nginx
sudo nginx -t && sudo systemctl restart nginx

echo ""
echo "=== 部署完成 ==="
echo "后端API: http://localhost:8000"
echo "前端访问: http://服务器IP"

九、访问地址汇总

服务 地址
后端 API http://localhost:8000
API 文档 http://localhost:8000/docs
前端应用 http://服务器IP:80

如有问题,请检查日志:

bash 复制代码
# 后端
sudo journalctl -u xwzx-news-backend -n 50

# Nginx
sudo tail -20 /var/log/nginx/error.log
相关推荐
budingxiaomoli1 小时前
多机部署,负载均衡-LoadBalancer
运维·spring cloud·负载均衡
WL_Aurora1 小时前
Python 算法基础篇之树和二叉树
python·算法
小郑加油2 小时前
python学习Day11:认识与创建CSV文件
开发语言·python·学习
Pkmer2 小时前
Java程序员大战Python面向对象
python·ai编程
小龙报2 小时前
【Coze-AI智能体平台】低代码省时高效:Coze 应用开发全流程指南
java·人工智能·python·深度学习·低代码·chatgpt·交互
技术钱2 小时前
LCEL表达式与Runnable可运行协议
python
Echo_NGC22372 小时前
【论文解读】Attention Is All You Need —— AI 时代的“开山之作“,经典中的经典(transformer小白导读)
人工智能·python·深度学习·神经网络·机器学习·conda·transformer
JesseDev2 小时前
Docker lnmp环境快速搭建开箱即用
运维·docker·容器