Python 全栈开发 2026:FastAPI + Vue3 + Docker 从零到部署完整指南 Python 全栈开发 2026FastAPI Vue3 Docker 从零到部署完整指南一、引言2026年的Python全栈开发核心技术栈已经明确FastAPI后端 Vue 3前端 Docker部署。这套组合是企业中使用最广泛的Python全栈方案兼顾了开发效率、运行性能和运维便利性。本文将提供一份完整的从零到部署的全栈开发指南包含项目结构、前后端联调、数据库设计和生产部署全程可操作、可落地。二、整体架构设计2.1 技术栈选型层级技术选型说明前端框架Vue 3 TypeScriptComposition API, 响应式系统构建工具Vite极速开发体验UI组件库Element Plus成熟的企业级组件库状态管理PiniaVue 3 官方推荐后端框架FastAPI 2.0原生异步、自动文档ORMSQLAlchemy 2.0异步支持数据库PostgreSQL最先进的开源关系型数据库缓存Redis高性能缓存容器化Docker Docker Compose一键部署反向代理Nginx静态文件 API代理2.2 项目结构fullstack-app/ ├── backend/ │ ├── app/ │ │ ├── main.py │ │ ├── config.py │ │ ├── dependencies.py │ │ ├── models/ │ │ ├── schemas/ │ │ ├── services/ │ │ ├── repositories/ │ │ └── routers/ │ ├── alembic/ │ ├── tests/ │ ├── Dockerfile │ └── requirements.txt ├── frontend/ │ ├── src/ │ │ ├── components/ │ │ ├── views/ │ │ ├── stores/ │ │ ├── api/ │ │ ├── router/ │ │ └── App.vue │ ├── Dockerfile │ ├── vite.config.ts │ └── package.json ├── nginx/ │ └── nginx.conf ├── docker-compose.yml └── .env三、后端开发3.1 配置管理# backend/app/config.pyfrompydantic_settingsimportBaseSettingsfromtypingimportListclassSettings(BaseSettings):PROJECT_NAME:strFullstack AppVERSION:str1.0.0ENVIRONMENT:strdevelopmentDEBUG:boolTrue# 数据库DATABASE_URL:strpostgresqlasyncpg://user:passwordlocalhost:5432/appREDIS_URL:strredis://localhost:6379/0# JWTJWT_SECRET_KEY:stryour-secret-key-change-in-productionJWT_ALGORITHM:strHS256JWT_EXPIRE_MINUTES:int60# CORSCORS_ORIGINS:List[str][http://localhost:5173]model_config{env_file:.env}settingsSettings()3.2 产品管理 API# backend/app/routers/products.pyfromfastapiimportAPIRouter,HTTPException,status,QueryfromtypingimportList,Optionalfromapp.dependenciesimportDBSession,CurrentUser,Paginationfromapp.schemas.productimportProductCreate,ProductResponse,ProductUpdatefromapp.services.product_serviceimportProductService routerAPIRouter()router.post(/,response_modelProductResponse,status_codestatus.HTTP_201_CREATED)asyncdefcreate_product(data:ProductCreate,db:DBSession,user:CurrentUser):serviceProductService(db)returnawaitservice.create(data,user[id])router.get(/,response_modeldict)asyncdeflist_products(db:DBSession,pagination:Pagination,search:Optional[str]Query(None),category:Optional[str]Query(None),min_price:Optional[float]Query(None),max_price:Optional[float]Query(None),sort_by:Optional[str]Query(created_at),sort_order:Optional[str]Query(desc),):serviceProductService(db)items,totalawaitservice.list_with_filters(offsetpagination[offset],limitpagination[page_size],searchsearch,categorycategory,min_pricemin_price,max_pricemax_price,sort_bysort_by,sort_ordersort_order,)return{items:items,total:total,page:pagination[page],page_size:pagination[page_size],total_pages:(totalpagination[page_size]-1)//pagination[page_size],}router.get(/{product_id},response_modelProductResponse)asyncdefget_product(product_id:str,db:DBSession):serviceProductService(db)productawaitservice.get_by_id(product_id)ifnotproduct:raiseHTTPException(status_code404,detail产品不存在)returnproductrouter.put(/{product_id},response_modelProductResponse)asyncdefupdate_product(product_id:str,data:ProductUpdate,db:DBSession,user:CurrentUser):serviceProductService(db)productawaitservice.update(product_id,data,user[id])ifnotproduct:raiseHTTPException(status_code404,detail产品不存在)returnproductrouter.delete(/{product_id},status_codestatus.HTTP_204_NO_CONTENT)asyncdefdelete_product(product_id:str,db:DBSession,user:CurrentUser):ifuser[role]!admin:raiseHTTPException(status_code403,detail权限不足)serviceProductService(db)successawaitservice.delete(product_id)ifnotsuccess:raiseHTTPException(status_code404,detail产品不存在)四、前端开发4.1 API 封装// frontend/src/api/client.tsimportaxiosfromaxios;import{useAuthStore}from/stores/auth;importrouterfrom/router;constapiClientaxios.create({baseURL:import.meta.env.VITE_API_BASE_URL||/api,timeout:10000,headers:{Content-Type:application/json,},});// 请求拦截器apiClient.interceptors.request.use((config){constauthStoreuseAuthStore();if(authStore.token){config.headers.AuthorizationBearer${authStore.token};}returnconfig;},(error)Promise.reject(error));// 响应拦截器apiClient.interceptors.response.use((response)response.data,(error){if(error.response?.status401){constauthStoreuseAuthStore();authStore.logout();router.push(/login);}returnPromise.reject(error);});exportdefaultapiClient;4.2 产品管理 API// frontend/src/api/products.tsimportapiClientfrom./client;exportinterfaceProduct{id:string;name:string;description:string;price:number;category:string;stock:number;image_url:string;created_at:string;updated_at:string;}exportinterfaceProductListParams{page?:number;page_size?:number;search?:string;category?:string;min_price?:number;max_price?:number;sort_by?:string;sort_order?:string;}exportinterfaceProductListResponse{items:Product[];total:number;page:number;page_size:number;total_pages:number;}exportconstproductApi{list(params:ProductListParams{}){returnapiClient.get(/v1/products/,{params})asPromiseProductListResponse;},get(id:string){returnapiClient.get(/v1/products/${id})asPromiseProduct;},create(data:OmitProduct,id|created_at|updated_at){returnapiClient.post(/v1/products/,data)asPromiseProduct;},update(id:string,data:PartialProduct){returnapiClient.put(/v1/products/${id},data)asPromiseProduct;},delete(id:string){returnapiClient.delete(/v1/products/${id});},};4.3 Pinia 状态管理// frontend/src/stores/products.tsimport{defineStore}frompinia;import{ref,computed}fromvue;import{productApi,Product,ProductListParams}from/api/products;exportconstuseProductStoredefineStore(products,(){constitemsrefProduct[]([]);consttotalref(0);constloadingref(false);consterrorrefstring|null(null);constcurrentPageref(1);constpageSizeref(10);constfiltersrefProductListParams({});consttotalPagescomputed(()Math.ceil(total.value/pageSize.value));asyncfunctionfetchProducts(params?:ProductListParams){loading.valuetrue;error.valuenull;try{constmergedParams{page:currentPage.value,page_size:pageSize.value,...filters.value,...params,};constresponseawaitproductApi.list(mergedParams);items.valueresponse.items;total.valueresponse.total;currentPage.valueresponse.page;if(params){filters.value{...filters.value,...params};}}catch(e:any){error.valuee.response?.data?.detail||获取产品列表失败;}finally{loading.valuefalse;}}asyncfunctioncreateProduct(data:OmitProduct,id|created_at|updated_at){constproductawaitproductApi.create(data);awaitfetchProducts();returnproduct;}asyncfunctionupdateProduct(id:string,data:PartialProduct){constproductawaitproductApi.update(id,data);constindexitems.value.findIndex((item)item.idid);if(index!-1){items.value[index]product;}returnproduct;}asyncfunctiondeleteProduct(id:string){awaitproductApi.delete(id);items.valueitems.value.filter((item)item.id!id);total.value--;}return{items,total,loading,error,currentPage,pageSize,filters,totalPages,fetchProducts,createProduct,updateProduct,deleteProduct,};});4.4 Vue 3 组合式组件!-- frontend/src/views/ProductList.vue -- script setup langts import { onMounted, ref } from vue; import { useProductStore } from /stores/products; import { ElMessage, ElMessageBox } from element-plus; import type { Product } from /api/products; import ProductForm from /components/ProductForm.vue; const store useProductStore(); const showForm ref(false); const editingProduct refProduct | null(null); const searchQuery ref(); onMounted(() { store.fetchProducts(); }); function handleSearch() { store.fetchProducts({ search: searchQuery.value || undefined }); } function handlePageChange(page: number) { store.currentPage page; store.fetchProducts(); } function handleCreate() { editingProduct.value null; showForm.value true; } function handleEdit(product: Product) { editingProduct.value { ...product }; showForm.value true; } async function handleDelete(product: Product) { try { await ElMessageBox.confirm( 确定要删除产品「${product.name}」吗, 确认删除, { type: warning } ); await store.deleteProduct(product.id); ElMessage.success(删除成功); } catch { // 取消操作 } } async function handleFormSubmit(data: any) { try { if (editingProduct.value) { await store.updateProduct(editingProduct.value.id, data); ElMessage.success(更新成功); } else { await store.createProduct(data); ElMessage.success(创建成功); } showForm.value false; } catch (e: any) { ElMessage.error(e.response?.data?.detail || 操作失败); } } /script template div classproduct-list div classtoolbar el-input v-modelsearchQuery placeholder搜索产品... keyup.enterhandleSearch stylewidth: 300px template #append el-button clickhandleSearch搜索/el-button /template /el-input el-button typeprimary clickhandleCreate新增产品/el-button /div el-table :datastore.items v-loadingstore.loading stripe el-table-column propname label产品名称 / el-table-column propcategory label分类 width120 / el-table-column propprice label价格 width120 template #default{ row } ¥{{ row.price.toFixed(2) }} /template /el-table-column el-table-column propstock label库存 width100 / el-table-column label操作 width200 template #default{ row } el-button sizesmall clickhandleEdit(row)编辑/el-button el-button sizesmall typedanger clickhandleDelete(row) 删除 /el-button /template /el-table-column /el-table el-pagination v-model:current-pagestore.currentPage :page-sizestore.pageSize :totalstore.total layouttotal, prev, pager, next current-changehandlePageChange / ProductForm v-ifshowForm :producteditingProduct submithandleFormSubmit cancelshowForm false / /div /template五、Docker 部署5.1 docker-compose.ymlversion:3.8services:backend:build:./backendcontainer_name:fullstack-backendports:-8000:8000env_file:-.envdepends_on:postgres:condition:service_healthyredis:condition:service_startedrestart:unless-stoppednetworks:-app-networkfrontend:build:./frontendcontainer_name:fullstack-frontendports:-3000:80depends_on:-backendrestart:unless-stoppednetworks:-app-networkpostgres:image:postgres:16-alpinecontainer_name:fullstack-postgresenvironment:POSTGRES_USER:${POSTGRES_USER:-app}POSTGRES_PASSWORD:${POSTGRES_PASSWORD:-app_password}POSTGRES_DB:${POSTGRES_DB:-fullstack}volumes:-postgres_data:/var/lib/postgresql/datahealthcheck:test:[CMD-SHELL,pg_isready -U ${POSTGRES_USER:-app}]interval:10stimeout:5sretries:5networks:-app-networkredis:image:redis:7-alpinecontainer_name:fullstack-redisvolumes:-redis_data:/datanetworks:-app-networknginx:image:nginx:alpinecontainer_name:fullstack-nginxports:-80:80volumes:-./nginx/nginx.conf:/etc/nginx/nginx.conf:rodepends_on:-backend-frontendrestart:unless-stoppednetworks:-app-networkvolumes:postgres_data:redis_data:networks:app-network:driver:bridge5.2 Nginx 配置events { worker_connections 1024; } http { upstream backend { server backend:8000; } upstream frontend { server frontend:80; } server { listen 80; # 前端静态资源 location / { proxy_pass http://frontend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # API 代理 location /api/ { proxy_pass http://backend/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; } # WebSocket 支持 location /ws/ { proxy_pass http://backend/ws/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; } } }六、总结FastAPI Vue 3 Docker的全栈技术栈组合在2026年已经成为Python全栈开发的事实标准。这套组合的优势在于FastAPI原生异步、自动文档、类型安全开发效率极高Vue 3Composition API、响应式系统、Pinia状态管理前端开发体验极佳Docker一键部署、环境隔离、易于扩展运维成本极低完整的全栈开发流程先设计数据模型→编写后端API→定义Pydantic Schema→开发前端页面→前后端联调→Docker部署。每一步都有清晰的最佳实践开发者可以专注于业务逻辑而非基础设施。对于想要快速交付全栈项目的团队来说这套技术栈组合是2026年最高效的选择。