当前位置: 首页 > news >正文

本地项目云服务器部署

本地项目上线:云服务器部署流程

1. 文档目标

本文记录一个本地项目部署到云服务器并最终完成正式网站上线的流程。

部署目标包括:

  • 将本地开发完成的项目运行到阿里云服务器

  • 使项目能够通过公网访问

  • 使用 Docker 作为运行环境

  • 使用 Nginx 作为反向代理

  • 后续接入域名解析与 HTTPS

本文不展开项目业务本身,只聚焦部署流程与部署过程中涉及的关键知识点。


2. 服务器登录与初始化

2.1 登录方式

在实际操作中,可以通过两种方式进入服务器:

  • 阿里云 Workbench

  • 本地终端通过 SSH 登录

补充说明:

  • Workbench 是阿里云提供的网页版远程终端

  • SSH 是一种远程登录协议,可以从本地终端直接连接服务器

  • Workbench 和 SSH 都能进入服务器,但入口不同

2.2 初始化服务器

服务器登录成功后,需要进行基础初始化:

  • 更新软件包索引

  • 安装基础工具

  • 安装 Docker

  • 验证 Docker 是否安装成功

  • 创建项目部署目录

我的部署目录统一使用:

/opt/resume-assistant

这样做的好处是:

  • 路径清晰

  • 便于统一管理项目文件、配置文件和数据目录

  • 符合 Linux 服务器上的项目部署习惯


3. 项目文件准备与上传

3.1 从 GitHub 拉取代码

服务器上的项目代码通过 GitHub 获取,而不是直接把整个开发目录复制到服务器。

这样做的好处是:

  • 代码来源清晰

  • 版本管理方便

  • 后续更新代码有统一入口

3.2 配置运行环境变量

项目运行需要.env文件,服务器上需要单独创建和配置。

.env中主要包括:

  • 模型提供商类型

  • API Key

  • 服务监听地址

  • 端口

  • 超时配置

  • CORS 配置

  • collection 名称等

3.3 创建数据目录

项目运行过程中需要独立的数据目录,例如:

data/self_resume data/uploads data/chroma/self_resume data/chroma/uploaded_docs

这些目录用于保存:

  • 私有 PDF 文件

  • 上传文件

  • 向量知识库数据

3.4 上传私密文件

一些内容不适合放进 GitHub,例如:

  • .env

  • 个人简历 PDF

  • 本地生成的向量库

因此这些文件需要单独上传到服务器。

补充说明:

  • 本地文件上传到服务器通常使用scp

  • scp基于 SSH 协议工作

  • 上传本地文件时,命令必须在本地终端执行,而不是在服务器终端执行


4. Docker 部署基础认知

Docker 在当前部署中的作用是:

  • 为项目提供统一运行环境

  • 避免服务器环境与本地环境不一致

  • 方便项目迁移和重启

4.1 镜像与容器

部署过程中需要区分三个概念:

  • Docker:容器化工具

  • 镜像:应用运行模板

  • 容器:镜像运行后的实例

可以理解为:

  • 镜像是“打包好的运行环境”

  • 容器是“真正跑起来的实例”

4.2 镜像与容器的关系

镜像构建完成后,可以用镜像创建容器。

需要特别理解的是:

  • 容器创建后就固定绑定到创建时的镜像

  • 后续即使重新构建了同名镜像,旧容器也不会自动更新

  • 发布新版本时,应删除旧容器,再基于新镜像启动新容器

4.3 tag 与 image ID

Docker 镜像有两个重要标识:

  • image ID:镜像真实身份

  • tag:镜像标签,例如latest

同名重新构建镜像时,本质上不是原地修改旧镜像,而是:

  • 创建新的镜像对象

  • 让相同的 tag 指向新镜像

4.4 镜像大小相关字段

docker images中常见两个字段:

  • CONTENT SIZE:镜像内容本身大小

  • DISK USAGE:镜像当前实际占用的磁盘空间估算

由于 Docker 镜像层可以共享,因此二者不一定相同。


5. 当前项目的 Docker 部署方案

5.1 原计划

最初的理想部署流程是:

  • 服务器拉取最新代码

  • 服务器直接执行docker build

  • 服务器本地构建镜像

  • 启动容器

5.2 实际问题

实际部署时发现:

  • 阿里云服务器访问 Docker Hub 不稳定

  • Dockerfile 中的基础镜像python:3.11-slim无法稳定拉取

  • 因此服务器本地docker build失败

5.3 最终采用的方案

针对上述问题,最终采用以下部署策略:

  1. 在本地电脑构建最新镜像

  2. 在本地导出镜像为 tar 文件

  3. 使用scp将镜像文件上传到服务器

  4. 在服务器执行docker load

  5. 删除旧容器

  6. 使用新镜像重新启动容器

该方案的本质是:

本地 build,服务器 run

这是当前环境下更稳定的发布方式。


6. 项目启动与服务验证

6.1 启动容器

容器启动时,需要:

  • 指定环境变量文件.env

  • 指定端口映射

  • 将服务器本地data/目录挂载到容器内

挂载数据目录的好处是:

  • 向量库不会因为容器重启而丢失

  • 上传文件和私有 PDF 可持久保存

  • 容器只是运行环境,数据仍保留在服务器磁盘上

6.2 初始化知识库

个人网站项目中,仅上传 PDF 还不够,还需要执行灌库流程。

灌库过程通常包括:

  • 读取 PDF

  • 切分文本

  • 调用 embedding 模型

  • 写入 Chroma 向量库

完成灌库后,问答助手才能基于知识库检索并回答问题。

6.3 服务检查

部署完成后,通过以下接口验证服务状态:

  • /health

  • /ready

其中:

  • /health用于检查服务是否正常启动

  • /ready用于检查服务是否真正具备可用条件,例如:

    • 是否存在个人简历 PDF

    • 模型配置是否正常

    • 运行环境是否完整

6.4 公网访问

服务启动后,需要在阿里云控制台放行应用端口,例如:

  • 8008

放行后即可通过公网 IP + 端口访问网站。


7. 部署过程中的问题排查

部署过程中遇到过多类问题,排查思路如下。

7.1 Docker Hub 拉取失败

现象:

  • docker build无法拉取基础镜像

  • 构建过程卡在python:3.11-slim

原因:

  • 服务器无法稳定访问 Docker Hub

解决方式:

  • 改为本地构建镜像并上传服务器

7.2 API Key 认证失败

现象:

  • 模型调用返回401

  • 灌库失败

原因可能包括:

  • API Key 错误

  • key 中包含隐藏空格

  • .env修改后容器未重启

  • 新 key 未正确传入容器

解决方式:

  • 更新.env

  • 重启容器

  • 再次执行灌库

7.3 公网无法访问

现象:

  • 本机curl可访问

  • 浏览器公网无法访问

原因:

  • 云平台防火墙未放行端口

解决方式:

  • 在阿里云控制台放行相应端口

7.4 前端Failed to fetch

现象:

  • 网站页面能打开

  • 问答助手请求失败

原因:

  • 前端 API 请求地址写死为127.0.0.1

  • 或者线上运行的容器仍是旧版本镜像

需要理解的是:

  • 服务器上的源码不一定等于容器中实际运行的代码

  • 本地修复代码后,如果没有重新 build 镜像并替换容器,线上仍然会运行旧逻辑

7.5 代码版本与容器版本不一致

这是部署中非常关键的认知:

  • 服务器目录里的代码只是源码

  • 容器运行的是镜像打包时的代码快照

  • 如果镜像没更新,线上效果就不会更新


8. Nginx 反向代理认知

8.1 Nginx 的作用

Nginx 是一个 Web 服务器,也可以作为反向代理服务器。

在本次部署中,Nginx 的作用是:

  • 接收公网标准端口请求

  • 将请求转发给 Docker 容器中的应用服务

8.2 为什么需要反向代理

在 Docker 部署完成后,项目最初是通过以下方式访问的:

http://公网IP:8008/

这种方式虽然可用,但不够正式。

引入 Nginx 后,可以将访问入口改为:

http://公网IP/

即:

  • 用户访问 80 端口

  • Nginx 转发到127.0.0.1:8008

8.3 反向代理的访问链路

引入 Nginx 后,访问链路变为:

浏览器 → Nginx → FastAPI 容器 → 项目服务

这是一种更标准的线上部署方式,也为后续域名和 HTTPS 做好了准备。


9. Nginx 实操配置

9.1 安装 Nginx

在服务器上安装 Nginx 后,需要:

  • 创建新的站点配置文件

  • 配置反向代理规则

  • 启用站点配置

  • 删除默认站点

  • 测试配置语法

  • 重启或重载 Nginx

9.2 反向代理核心配置

核心思路是:

  • 监听 80 端口

  • /请求转发到127.0.0.1:8008

9.3 默认页问题

部署过程中曾出现:

Welcome to nginx!

这说明:

  • Nginx 本身已安装成功

  • 但默认站点配置仍在生效

  • 自定义反向代理配置未真正接管请求

解决方式:

  • 删除默认站点配置

  • 启用自定义站点配置

  • reload Nginx

9.4 放行 80 端口

Nginx 配置完成后,还需要在阿里云控制台放行:

  • 80/tcp

放行成功后,网站即可通过不带端口的公网 IP 访问。


10. 域名解析

10.1 域名的作用

公网 IP 可以访问网站,但不适合作为长期正式入口。

域名的作用是:

  • 提供更易记的网址

  • 让网站更专业

  • 为 HTTPS 配置做准备

10.2 域名解析的意义

域名解析的本质是:

  • 将域名指向服务器公网 IP

当域名解析完成后,访问入口将从:

http://公网IP/

变为:

http://你的域名/

10.3 接入域名后需要做的事

域名解析完成后,还需要:

  • 修改 Nginx 的server_name

  • 让 Nginx 对域名请求生效


11. HTTPS 配置

11.1 为什么需要 HTTPS

HTTPS 的意义包括:

  • 提供加密传输

  • 避免浏览器提示“不安全”

  • 让网站更像正式线上服务

  • 满足个人网站上线的完整体验

11.2 HTTPS 与域名的关系

通常情况下,正式 HTTPS 证书绑定的是域名,而不是裸公网 IP。

因此实际步骤通常是:

  1. 域名解析到服务器

  2. 配置 Nginxserver_name

  3. 申请 SSL 证书

  4. 在 Nginx 中启用 HTTPS

  5. 将 HTTP 跳转到 HTTPS

11.3 当前阶段状态

当前部署已完成:

  • 云服务器部署

  • Docker 运行

  • Nginx 反向代理

  • 公网访问

后续待完成:

  • 域名解析正式生效

  • 配置 HTTPS

  • 形成最终正式网站入口


12. 当前部署架构总结

当前网站架构可以概括为:

浏览器 → 公网 IP / 域名 → Nginx → Docker 容器 → FastAPI 项目 → 知识库 / 模型 API

当前项目的发布策略为:

本地修改代码 → 本地构建镜像 → 本地导出镜像 → 上传到服务器 → 服务器导入镜像 → 删除旧容器 → 启动新容器

这是一种适合当前网络环境的稳定发布方式。


13. 附录:常用命令清单

13.1 SSH 登录

ssh admin@服务器公网IP

13.2 SCP 上传文件

scp 本地文件 admin@服务器公网IP:服务器目录

13.3 Docker 常用命令

查看镜像:

sudo docker images

查看容器:

sudo docker ps

删除容器:

sudo docker rm -f 容器名

导入镜像:

sudo docker load -i 镜像文件.tar

启动容器:

sudo docker run ...

查看磁盘占用:

sudo docker system df

清理悬空镜像:

sudo docker image prune -f

13.4 服务检查

curl http://127.0.0.1:8008/health curl http://127.0.0.1:8008/ready

13.5 Nginx 常用命令

测试配置:

sudo nginx -t

重启:

sudo systemctl restart nginx

重载配置:

sudo systemctl reload nginx

查看状态:

sudo systemctl status nginx --no-pager

13.6 端口检查

sudo ss -ltnp | grep 8008
http://www.jsqmd.com/news/639021/

相关文章:

  • nli-distilroberta-base安全与隐私考量:模型部署中的风险与缓解措施
  • 别再只写data()了!深入理解PyQt5 QAbstractItemModel中flags()和setData()的实战用法
  • YaeAchievement:3分钟搞定原神成就导出的终极解决方案
  • Rust的闭包语法分析
  • 小红书场景化内容杀招:把“卖产品”变成“卖生活“,本地商家高收藏笔记模板 - Redbook_CD
  • Mythos、OpenClaw、GLM-5.1 连续出现后,Agent 系统的测试边界开始重写
  • CUDA环境权限问题解析:从mmcv-full安装报错Permission denied到系统级解决方案
  • Adobe-GenP:轻松激活Adobe Creative Cloud的完整解决方案
  • SDXL 1.0电影级绘图工坊效果展示:同一提示词下5种预设风格生成效果全景对比
  • 视频封面批量制作工具完整使用指南:从素材准备到批量输出的操作全流程
  • React Fiber 调度优先级优化方案
  • 吉林省快到家家政服务有限公司简介与业务介绍 - 深圳昊客网络
  • 武汉佰利和建筑防水工程有限公司:东西湖区防水维修价格 - LYL仔仔
  • 从四个 Gateway 插件到 SAP_GWFND,读懂 AS ABAP 7.40 到 7.50 的架构转身
  • AIVideo实战案例:如何制作一个高质量的社交媒体短视频
  • 2025届最火的五大降重复率方案解析与推荐
  • 从零到一:如何用RoboMaster开发板C型构建你的第一个机器人控制系统
  • 2026年中国湖北江南专用汽车/湖北江南专用特种汽车有限公司高口碑品牌推荐 - 品牌宣传支持者
  • QMCDecode终极指南:轻松解锁QQ音乐加密格式,实现跨平台播放自由
  • 3分钟快速上手BetterNCM Installer:一键解锁网易云音乐插件系统终极攻略
  • YOLO11涨点优化:注意力魔改 | 引入Vision Mamba (Vim) 核心状态空间模块,打破Transformer计算瓶颈,实现高效全局感知
  • 医学影像AI新突破:拆解MedSegDiff-V2如何用‘频域魔法’解决分割边界模糊难题
  • C 语言面向对象风格封装的经典技巧(STM32F4 标准库实现)
  • LSB隐写术的克星:RS分析原理图解与实战避坑指南
  • 3分钟搞定网易云音乐插件管理:BetterNCM Installer完整指南
  • 2026年口碑好的视觉点胶机/精密视觉点胶机/喷射阀视觉点胶机行业内口碑厂家推荐 - 行业平台推荐
  • 洛谷-算法1-6-二分查找与二分答案2
  • 如何高效批量下载微博相册高清图片?Python多线程工具全解析
  • YOLO12模型在Web应用中的实时目标检测实现
  • 高效解锁QQ音乐加密音频:qmc-decoder完整技术指南