Python全栈实战:Docker Compose + Nginx 部署 FastAPI、Vue3 与 MySQL
Python全栈实战Docker Compose Nginx 部署 FastAPI、Vue3 与 MySQL完成一个全栈项目的开发只是第一步将它真正部署到生产环境并稳定运行才是更大的挑战。本文将带你从零开始使用Docker Compose和Nginx将FastAPI后端、Vue3前端和MySQL数据库部署为一个完整的生产级应用。这不仅是一个教程更是一套可复用的部署模板。一、最终架构概览浏览器 │ │ 80端口 ▼ Nginx反向代理 静态资源服务 │ ├── /api/* ──────► FastAPI:8000后端API ├── /static/* ───► Nginx直接返回静态文件 └── /* ──────────► Vue3前端静态页面 │ ▼ MySQL:3306数据库 │ ▼ Docker Volume数据持久化这套架构的核心设计思想Nginx作为统一入口处理静态资源、反向代理和负载均衡FastAPI只负责业务逻辑和API不处理静态文件Vue3编译为纯静态文件由Nginx直接服务MySQL通过Docker Volume持久化数据确保容器重启不丢失二、项目结构project/ ├── backend/ │ ├── app/ │ │ ├── __init__.py │ │ ├── main.py # FastAPI入口 │ │ ├── models.py # SQLAlchemy模型 │ │ ├── schemas.py # Pydantic模型 │ │ ├── crud.py # 数据库操作 │ │ ├── database.py # 数据库连接 │ │ └── routers/ # API路由 │ │ ├── __init__.py │ │ ├── auth.py # 认证路由 │ │ └── users.py # 用户路由 │ ├── requirements.txt │ ├── Dockerfile │ └── alembic/ # 数据库迁移 ├── frontend/ │ ├── src/ │ ├── package.json │ ├── vite.config.ts │ ├── Dockerfile │ └── nginx.conf # 前端Nginx配置 ├── nginx/ │ └── nginx.conf # 主Nginx配置 ├── docker-compose.yml └── .env三、FastAPI后端实现3.1 数据库连接# backend/app/database.pyfromsqlalchemyimportcreate_enginefromsqlalchemy.ext.declarativeimportdeclarative_basefromsqlalchemy.ormimportsessionmakerimportos DATABASE_URLos.getenv(DATABASE_URL,mysqlpymysql://user:passworddb:3306/app_db)enginecreate_engine(DATABASE_URL,pool_size20,max_overflow40,pool_pre_pingTrue,# 自动检测连接是否有效pool_recycle3600,# 每小时回收连接)SessionLocalsessionmaker(autocommitFalse,autoflushFalse,bindengine)Basedeclarative_base()defget_db():dbSessionLocal()try:yielddbfinally:db.close()3.2 用户模型# backend/app/models.pyfromsqlalchemyimportColumn,Integer,String,Boolean,DateTimefromsqlalchemy.sqlimportfuncfrom.databaseimportBaseclassUser(Base):__tablename__usersidColumn(Integer,primary_keyTrue,indexTrue)usernameColumn(String(50),uniqueTrue,indexTrue,nullableFalse)emailColumn(String(100),uniqueTrue,indexTrue,nullableFalse)hashed_passwordColumn(String(255),nullableFalse)is_activeColumn(Boolean,defaultTrue)is_superuserColumn(Boolean,defaultFalse)created_atColumn(DateTime(timezoneTrue),server_defaultfunc.now())updated_atColumn(DateTime(timezoneTrue),onupdatefunc.now())3.3 JWT认证# backend/app/routers/auth.pyfromdatetimeimportdatetime,timedeltafromfastapiimportAPIRouter,Depends,HTTPException,statusfromfastapi.securityimportOAuth2PasswordBearer,OAuth2PasswordRequestFormfromjoseimportJWTError,jwtfrompasslib.contextimportCryptContextfrompydanticimportBaseModel routerAPIRouter(prefix/auth,tags[认证])# 配置SECRET_KEYos.getenv(SECRET_KEY,your-secret-key-change-in-production)ALGORITHMHS256ACCESS_TOKEN_EXPIRE_MINUTES30pwd_contextCryptContext(schemes[bcrypt],deprecatedauto)oauth2_schemeOAuth2PasswordBearer(tokenUrl/api/auth/login)classToken(BaseModel):access_token:strtoken_type:strclassTokenData(BaseModel):username:str|NoneNonedefcreate_access_token(data:dict,expires_delta:timedelta|NoneNone):to_encodedata.copy()expiredatetime.utcnow()(expires_deltaortimedelta(minutes15))to_encode.update({exp:expire})returnjwt.encode(to_encode,SECRET_KEY,algorithmALGORITHM)router.post(/login,response_modelToken)asyncdeflogin(form_data:OAuth2PasswordRequestFormDepends(),db:SessionDepends(get_db)):userdb.query(User).filter(User.usernameform_data.username).first()ifnotuserornotpwd_context.verify(form_data.password,user.hashed_password):raiseHTTPException(status_codestatus.HTTP_401_UNAUTHORIZED,detail用户名或密码错误,headers{WWW-Authenticate:Bearer},)access_tokencreate_access_token(data{sub:user.username},expires_deltatimedelta(minutesACCESS_TOKEN_EXPIRE_MINUTES))return{access_token:access_token,token_type:bearer}asyncdefget_current_user(token:strDepends(oauth2_scheme),db:SessionDepends(get_db)):credentials_exceptionHTTPException(status_codestatus.HTTP_401_UNAUTHORIZED,detail无法验证凭据,headers{WWW-Authenticate:Bearer},)try:payloadjwt.decode(token,SECRET_KEY,algorithms[ALGORITHM])username:strpayload.get(sub)ifusernameisNone:raisecredentials_exceptionexceptJWTError:raisecredentials_exception userdb.query(User).filter(User.usernameusername).first()ifuserisNone:raisecredentials_exceptionreturnuser3.4 FastAPI应用入口# backend/app/main.pyfromfastapiimportFastAPIfromfastapi.middleware.corsimportCORSMiddlewarefrom.routersimportauth,users appFastAPI(title全栈应用API,version1.0.0,docs_url/api/docs,redoc_url/api/redoc,)# CORS配置app.add_middleware(CORSMiddleware,allow_origins[*],# 生产环境应限制具体域名allow_credentialsTrue,allow_methods[*],allow_headers[*],)# 注册路由app.include_router(auth.router,prefix/api)app.include_router(users.router,prefix/api)app.get(/api/health)asyncdefhealth_check():return{status:healthy,version:1.0.0}3.5 后端Dockerfile# backend/Dockerfile FROM python:3.12-slim WORKDIR /app # 安装系统依赖 RUN apt-get update apt-get install -y --no-install-recommends \ gcc \ default-libmysqlclient-dev \ rm -rf /var/lib/apt/lists/* # 安装Python依赖 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 创建非root用户 RUN useradd -m -u 1000 appuser chown -R appuser:appuser /app USER appuser # 使用uvicorn运行 CMD [uvicorn, app.main:app, --host, 0.0.0.0, --port, 8000, --workers, 4]四、Vue3前端4.1 Vite配置// frontend/vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueimport{resolve}frompathexportdefaultdefineConfig({plugins:[vue()],resolve:{alias:{:resolve(__dirname,src),},},server:{port:5173,proxy:{/api:{target:http://localhost:8000,changeOrigin:true,},},},build:{outDir:dist,assetsDir:assets,sourcemap:false,rollupOptions:{output:{manualChunks:{vue-vendor:[vue,vue-router,pinia],ui-vendor:[element-plus],},},},},})4.2 前端Dockerfile多阶段构建# frontend/Dockerfile # 阶段1构建 FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY . . RUN npm run build # 阶段2生产运行 FROM nginx:alpine COPY --frombuilder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD [nginx, -g, daemon off;]4.3 前端Nginx配置# frontend/nginx.conf server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; # Vue Router history模式 location / { try_files $uri $uri/ /index.html; } # 静态资源缓存 location /assets { expires 1y; add_header Cache-Control public, immutable; } # API代理 location /api/ { proxy_pass http://backend:8000/api/; 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; } }五、Docker Compose编排# docker-compose.ymlversion:3.8services:# MySQL数据库db:image:mysql:8.0container_name:app_dbrestart:alwaysenvironment:MYSQL_ROOT_PASSWORD:${MYSQL_ROOT_PASSWORD}MYSQL_DATABASE:${MYSQL_DATABASE}MYSQL_USER:${MYSQL_USER}MYSQL_PASSWORD:${MYSQL_PASSWORD}ports:-3306:3306volumes:-mysql_data:/var/lib/mysql-./db/init.sql:/docker-entrypoint-initdb.d/init.sqlhealthcheck:test:[CMD,mysqladmin,ping,-h,localhost]interval:10stimeout:5sretries:5networks:-app_network# FastAPI后端backend:build:context:./backenddockerfile:Dockerfilecontainer_name:app_backendrestart:alwaysenvironment:DATABASE_URL:mysqlpymysql://${MYSQL_USER}:${MYSQL_PASSWORD}db:3306/${MYSQL_DATABASE}SECRET_KEY:${SECRET_KEY}depends_on:db:condition:service_healthynetworks:-app_network# Vue3前端 Nginxfrontend:build:context:./frontenddockerfile:Dockerfilecontainer_name:app_frontendrestart:alwaysports:-80:80depends_on:-backendnetworks:-app_networkvolumes:mysql_data:driver:localnetworks:app_network:driver:bridge六、部署与运维6.1 启动服务# 构建并启动所有服务docker-composeup-d--build# 查看运行状态docker-composeps# 查看日志docker-composelogs-fbackend# 执行数据库迁移docker-composeexecbackend alembic upgradehead6.2 健康检查与监控# 健康检查端点curlhttp://localhost/api/health# 监控容器资源使用dockerstats# 查看数据库连接docker-composeexecdb mysql-uuser-p-eSHOW PROCESSLIST6.3 备份策略# 备份MySQL数据docker-composeexecdb mysqldump-uuser-papp_dbbackup_$(date%Y%m%d).sql# 备份Docker Volumedockerrun--rm-vapp_mysql_data:/data-v$(pwd):/backup alpinetarczf /backup/mysql_backup.tar.gz-C/data.6.4 生产环境优化清单启用HTTPS使用Let’s Encrypt Certbot自动获取SSL证书限流保护在Nginx中配置rate limiting日志轮转配置Docker日志驱动为json-file并设置max-size资源限制在docker-compose.yml中设置CPU和内存限制秘密管理使用Docker Secrets或外部密钥管理服务监控告警集成Prometheus Grafana七、常见问题排查问题1后端无法连接数据库# 检查数据库是否就绪docker-composeexecbackend python-c import pymysql conn pymysql.connect(hostdb, useruser, passwordpassword, databaseapp_db) print(连接成功) conn.close() 问题2前端API请求404检查Nginx的proxy_pass配置确保URL路径正确映射。特别注意proxy_pass末尾的斜杠。问题3容器内存泄漏使用docker stats监控内存使用在docker-compose.yml中设置mem_limit和mem_reservation。八、总结通过Docker Compose Nginx的部署方案我们实现了一套完整的生产级全栈应用部署架构。这套方案的核心优势在于环境一致性Docker确保开发、测试、生产环境完全一致一键部署docker-compose up -d即可启动整个应用栈服务隔离每个服务在独立容器中运行互不干扰水平扩展通过docker-compose up -d --scale backend3轻松扩展后端实例数据持久化Docker Volume确保数据在容器重启后不丢失这套方案可以直接作为新项目的部署模板只需替换业务代码和配置即可快速上线。

相关新闻

学术研究的“瑞士军刀”:宏智树AI全流程科研平台深度解析

学术研究的“瑞士军刀”:宏智树AI全流程科研平台深度解析

如果你正在写论文,无论是本科毕业论文还是硕士研究,大概都经历过这样的场景:开题报告用一个模板,文献综述靠手动翻知网,数据分析打开SPSS对着教程一步步操作,查重又要切换到另一个平台——每个环节都要折腾…

2026/8/7 23:10:16 阅读更多 →
一场关于“源头”的反思:当AI让数据治理回归业务本质(

一场关于“源头”的反思:当AI让数据治理回归业务本质(

上周,托山东CIO联盟的福,旁听了一场线上闭门交流,主题挺硬核——“AI赋能的源端数据质量改造”。老实说,刚开始我内心毫无波澜,甚至想嗑瓜子。毕竟“数据治理”这四个字,耳朵都听出茧子了。这些年&#xff…

2026/8/8 6:19:41 阅读更多 →
面试问权限日志可观测,我才知道Demo和上线之间差了多少

面试问权限日志可观测,我才知道Demo和上线之间差了多少

聊《别急着重做程序员就业,先看岗位到底在筛什么》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要摘要:2026年的大模型岗位招聘,已经过了"会调API就能上岗"的阶段。…

2026/8/7 23:54:58 阅读更多 →

最新新闻

让老Mac焕发新生:OpenCore Legacy Patcher完整操作指南

让老Mac焕发新生:OpenCore Legacy Patcher完整操作指南

让老Mac焕发新生:OpenCore Legacy Patcher完整操作指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 还在为2015年前的Mac无法升级最新macOS而苦…

2026/8/8 13:06:57 阅读更多 →
Markmap终极指南:3种高效方案实现Markdown到思维导图的专业转换

Markmap终极指南:3种高效方案实现Markdown到思维导图的专业转换

Markmap终极指南:3种高效方案实现Markdown到思维导图的专业转换 【免费下载链接】markmap Build mindmaps with plain text 项目地址: https://gitcode.com/gh_mirrors/ma/markmap 在当今信息密集的开发环境中,Markmap思维导图转换工具为开发者提…

2026/8/8 13:06:57 阅读更多 →
百度网盘Mac版免费解锁SVIP速度:完整加速指南与安装教程

百度网盘Mac版免费解锁SVIP速度:完整加速指南与安装教程

百度网盘Mac版免费解锁SVIP速度:完整加速指南与安装教程 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 你是否厌倦了百度网盘Mac版那令人沮…

2026/8/8 13:06:57 阅读更多 →
B站视频免费下载终极指南:跨平台批量下载神器快速上手教程

B站视频免费下载终极指南:跨平台批量下载神器快速上手教程

B站视频免费下载终极指南:跨平台批量下载神器快速上手教程 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirro…

2026/8/8 13:06:57 阅读更多 →
Git子模块初始化失败排查与解决方案

Git子模块初始化失败排查与解决方案

1. 问题现象与背景分析遇到git submodule update --init --recursive命令执行失败时,通常会在终端看到类似这样的报错信息:fatal: clone of https://github.com/xxx/yyy.git into submodule path /path/to/submodule failed Failed to clone submodules/…

2026/8/8 13:06:57 阅读更多 →
手机变身启动盘神器:EtchDroid终极指南,无需电脑制作系统安装盘

手机变身启动盘神器:EtchDroid终极指南,无需电脑制作系统安装盘

手机变身启动盘神器:EtchDroid终极指南,无需电脑制作系统安装盘 【免费下载链接】etchdroid An application to write OS images to USB drives, on Android, no root required. 项目地址: https://gitcode.com/gh_mirrors/et/etchdroid 你是否遇…

2026/8/8 13:05:57 阅读更多 →

日新闻

AI多智能体时代来临,读懂MCP与A2A架构,抢占企业数字化新风口

AI多智能体时代来临,读懂MCP与A2A架构,抢占企业数字化新风口

当下AI应用飞速普及,无数企业下场搭建智能体系统,可落地阶段难题接踵而至:上下文无限堆积频繁爆栈、AI工具调用准确率低下、Token成本居高不下、企业数据权限混乱暗藏安全隐患……很多团队卡在架构搭建环节,空有前沿技术概念&…

2026/8/8 0:00:07 阅读更多 →
PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码

PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码

PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码 【免费下载链接】php-qrcode A PHP QR Code generator and reader with a user-friendly API. 项目地址: https://gitcode.com/gh_mirrors/ph/php-qrcode 在当今数字时代,二维码已…

2026/8/8 0:00:08 阅读更多 →
UniApp微信小程序隐私保护组件开发:从原理到实战

UniApp微信小程序隐私保护组件开发:从原理到实战

1. 项目缘起:为什么我们需要一个隐私保护通用组件?最近在维护一个基于uniapp开发的微信小程序矩阵时,我遇到了一个非常棘手的问题。随着平台对用户隐私保护的要求越来越严格,几乎每一个新版本发布,或者在某些特定机型&…

2026/8/8 0:00:08 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/8 8:58:26 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/7 23:24:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/7 17:02:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/7 23:54:54 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/7 17:02:36 阅读更多 →