本地项目云服务器部署
本地项目上线云服务器部署流程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本地生成的向量库因此这些文件需要单独上传到服务器。补充说明本地文件上传到服务器通常使用scpscp基于 SSH 协议工作上传本地文件时命令必须在本地终端执行而不是在服务器终端执行4. Docker 部署基础认知Docker 在当前部署中的作用是为项目提供统一运行环境避免服务器环境与本地环境不一致方便项目迁移和重启4.1 镜像与容器部署过程中需要区分三个概念Docker容器化工具镜像应用运行模板容器镜像运行后的实例可以理解为镜像是“打包好的运行环境”容器是“真正跑起来的实例”4.2 镜像与容器的关系镜像构建完成后可以用镜像创建容器。需要特别理解的是容器创建后就固定绑定到创建时的镜像后续即使重新构建了同名镜像旧容器也不会自动更新发布新版本时应删除旧容器再基于新镜像启动新容器4.3 tag 与 image IDDocker 镜像有两个重要标识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 最终采用的方案针对上述问题最终采用以下部署策略在本地电脑构建最新镜像在本地导出镜像为 tar 文件使用scp将镜像文件上传到服务器在服务器执行docker load删除旧容器使用新镜像重新启动容器该方案的本质是本地 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:80088.3 反向代理的访问链路引入 Nginx 后访问链路变为浏览器 → Nginx → FastAPI 容器 → 项目服务这是一种更标准的线上部署方式也为后续域名和 HTTPS 做好了准备。9. Nginx 实操配置9.1 安装 Nginx在服务器上安装 Nginx 后需要创建新的站点配置文件配置反向代理规则启用站点配置删除默认站点测试配置语法重启或重载 Nginx9.2 反向代理核心配置核心思路是监听 80 端口将/请求转发到127.0.0.1:80089.3 默认页问题部署过程中曾出现Welcome to nginx!这说明Nginx 本身已安装成功但默认站点配置仍在生效自定义反向代理配置未真正接管请求解决方式删除默认站点配置启用自定义站点配置reload Nginx9.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 为什么需要 HTTPSHTTPS 的意义包括提供加密传输避免浏览器提示“不安全”让网站更像正式线上服务满足个人网站上线的完整体验11.2 HTTPS 与域名的关系通常情况下正式 HTTPS 证书绑定的是域名而不是裸公网 IP。因此实际步骤通常是域名解析到服务器配置 Nginxserver_name申请 SSL 证书在 Nginx 中启用 HTTPS将 HTTP 跳转到 HTTPS11.3 当前阶段状态当前部署已完成云服务器部署Docker 运行Nginx 反向代理公网访问后续待完成域名解析正式生效配置 HTTPS形成最终正式网站入口12. 当前部署架构总结当前网站架构可以概括为浏览器 → 公网 IP / 域名 → Nginx → Docker 容器 → FastAPI 项目 → 知识库 / 模型 API当前项目的发布策略为本地修改代码 → 本地构建镜像 → 本地导出镜像 → 上传到服务器 → 服务器导入镜像 → 删除旧容器 → 启动新容器这是一种适合当前网络环境的稳定发布方式。13. 附录常用命令清单13.1 SSH 登录ssh admin服务器公网IP13.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 -f13.4 服务检查curl http://127.0.0.1:8008/health curl http://127.0.0.1:8008/ready13.5 Nginx 常用命令测试配置sudo nginx -t重启sudo systemctl restart nginx重载配置sudo systemctl reload nginx查看状态sudo systemctl status nginx --no-pager13.6 端口检查sudo ss -ltnp | grep 8008