从零搭建企业 AI 办公助手:Docker 一键部署与完整源码实战
AI办公 Docker部署教程|附源码
在企业数字化办公场景中,AI办公工具正在成为提升效率的重要基础设施。无论是智能写作、会议纪要生成、文档总结、知识库问答,还是自动化邮件、合同审阅、数据分析,AI都可以帮助团队减少重复劳动,把更多时间投入到更有价值的工作中。
不过,很多人在部署AI办公系统时会遇到不少问题:环境依赖复杂、Python版本不一致、数据库配置繁琐、前后端联调困难、服务器迁移麻烦等。为了解决这些问题,本文将带你从零开始,使用 Docker + Docker Compose 部署一个可运行的 AI办公系统,并提供一套简化版源码示例,方便你根据实际业务继续扩展。
本文适合以下读者:
- 想快速搭建AI办公系统的开发者;
- 想把AI能力接入公司内部办公流程的技术负责人;
- 熟悉基础Linux命令,但不想被复杂环境折腾的运维人员;
- 希望学习 Docker 部署 AI 应用的初学者。
一、项目效果说明
本文要部署的是一个简化版 AI办公系统,主要包含以下功能:
-
AI智能写作
- 输入主题,自动生成文章、邮件、总结、方案等内容。
-
文档总结
- 输入一段长文本,AI自动提炼核心要点。
-
办公问答助手
- 可以向AI提问,例如“帮我写一份周报”“整理会议纪要模板”。
-
前后端分离
- 后端使用 FastAPI;
- 前端使用 Vue 3;
- 数据库使用 MySQL;
- 缓存可选 Redis;
- 通过 Docker Compose 一键启动。
-
支持大模型接口
- 可以接入 OpenAI、通义千问、智谱、DeepSeek、Claude 或本地大模型接口;
- 本文以通用 API 调用方式演示,实际可自行替换。
二、整体技术架构
本项目采用比较常见的前后端分离架构:
用户浏览器
|
v
前端 Vue 3 / Nginx
|
v
后端 FastAPI
|
+---- MySQL 数据库
|
+---- Redis 缓存,可选
|
+---- 大模型 API 服务
技术栈说明
| 模块 | 技术 |
|---|---|
| 前端 | Vue 3、Vite、Axios、Element Plus |
| 后端 | Python、FastAPI、Uvicorn |
| 数据库 | MySQL 8 |
| 缓存 | Redis |
| 容器化 | Docker、Docker Compose |
| Web服务 | Nginx |
| AI接口 | OpenAI兼容接口或其他大模型API |
三、服务器环境准备
建议服务器配置如下:
| 项目 | 推荐配置 |
|---|---|
| CPU | 2核及以上 |
| 内存 | 4GB及以上 |
| 磁盘 | 20GB及以上 |
| 系统 | Ubuntu 20.04 / 22.04、Debian、CentOS |
| 网络 | 可访问大模型API |
如果你只是在本地测试,也可以使用 Windows + Docker Desktop 或 macOS + Docker Desktop。
四、安装 Docker 和 Docker Compose
如果你的服务器还没有安装 Docker,可以参考以下命令。
1. Ubuntu / Debian 安装 Docker
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
2. 验证 Docker 是否安装成功
docker -v
docker compose version
如果能够看到版本号,说明安装成功。
3. 设置 Docker 开机自启
sudo systemctl enable docker
sudo systemctl start docker
五、项目目录结构
我们创建一个名为 ai-office-docker 的项目目录:
mkdir ai-office-docker
cd ai-office-docker
推荐目录结构如下:
ai-office-docker
├── backend
│ ├── app
│ │ ├── main.py
│ │ ├── config.py
│ │ ├── database.py
│ │ ├── models.py
│ │ ├── schemas.py
│ │ └── ai_service.py
│ ├── requirements.txt
│ └── Dockerfile
├── frontend
│ ├── src
│ │ ├── App.vue
│ │ └── main.js
│ ├── index.html
│ ├── package.json
│ ├── vite.config.js
│ ├── nginx.conf
│ └── Dockerfile
├── docker-compose.yml
└── .env
这个目录中,backend 是后端服务,frontend 是前端页面,docker-compose.yml 用于统一编排所有服务。
六、后端源码
后端使用 FastAPI 编写,负责接收前端请求、调用AI模型接口,并将部分记录保存到数据库中。
1. backend/requirements.txt
fastapi==0.111.0
uvicorn[standard]==0.30.1
pydantic==2.7.4
pydantic-settings==2.3.4
SQLAlchemy==2.0.31
PyMySQL==1.1.1
requests==2.32.3
python-dotenv==1.0.1
2. backend/app/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
mysql_host: str = "mysql"
mysql_port: int = 3306
mysql_user: str = "ai_office"
mysql_password: str = "ai_office_pass"
mysql_database: str = "ai_office"
ai_api_key: str = ""
ai_api_base: str = "https://api.openai.com/v1"
ai_model: str = "gpt-4o-mini"
class Config:
env_file = ".env"
settings = Settings()
3. backend/app/database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from app.config import settings
DATABASE_URL = (
f"mysql+pymysql://{settings.mysql_user}:{settings.mysql_password}"
f"@{settings.mysql_host}:{settings.mysql_port}/{settings.mysql_database}"
"?charset=utf8mb4"
)
engine = create_engine(
DATABASE_URL,
pool_pre_ping=True,
pool_recycle=3600
)
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine
)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
4. backend/app/models.py
from sqlalchemy import Column, Integer, String, Text, DateTime
from sqlalchemy.sql import func
from app.database import Base
class AiRecord(Base):
__tablename__ = "ai_records"
id = Column(Integer, primary_key=True, index=True)
task_type = Column(String(50), nullable=False)
prompt = Column(Text, nullable=False)
result = Column(Text, nullable=False)
created_at = Column(DateTime, server_default=func.now())
5. backend/app/schemas.py
from pydantic import BaseModel
class AiRequest(BaseModel):
task_type: str
prompt: str
class AiResponse(BaseModel):
task_type: str
prompt: str
result: str
6. backend/app/ai_service.py
这里使用兼容 OpenAI 格式的接口调用方式。很多国内外模型服务商都支持类似格式,你只需要修改 .env 中的 AI_API_BASE、AI_API_KEY 和 AI_MODEL 即可。
import requests
from app.config import settings
def call_ai_model(task_type: str, prompt: str) -> str:
system_prompt = build_system_prompt(task_type)
url = f"{settings.ai_api_base}/chat/completions"
headers = {
"Authorization": f"Bearer {settings.ai_api_key}",
"Content-Type": "application/json"
}
payload = {
"model": settings.ai_model,
"messages": [
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": prompt
}
],
"temperature": 0.7
}
try:
response = requests.post(
url,
headers=headers,
json=payload,
timeout=60
)
response.raise_for_status()
data = response.json()
return data["choices"][0]["message"]["content"]
except Exception as e:
return f"AI接口调用失败:{str(e)}"
def build_system_prompt(task_type: str) -> str:
if task_type == "write":
return "你是一个专业的AI办公写作助手,擅长撰写文章、邮件、报告和方案。"
elif task_type == "summary":
return "你是一个专业的文档总结助手,请用简洁、清晰、有条理的方式总结用户输入内容。"
elif task_type == "meeting":
return "你是一个会议纪要助手,请根据用户输入整理会议主题、重点事项、待办任务和负责人。"
else:
return "你是一个高效、准确、专业的AI办公助手。"
7. backend/app/main.py
from fastapi import FastAPI, Depends
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from app.database import Base, engine, get_db
from app.models import AiRecord
from app.schemas import AiRequest, AiResponse
from app.ai_service import call_ai_model
Base.metadata.create_all(bind=engine)
app = FastAPI(
title="AI Office API",
description="AI办公系统后端接口",
version="1.0.0"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def index():
return {
"message": "AI Office API is running"
}
@app.post("/api/ai", response_model=AiResponse)
def ai_generate(request: AiRequest, db: Session = Depends(get_db)):
result = call_ai_model(request.task_type, request.prompt)
record = AiRecord(
task_type=request.task_type,
prompt=request.prompt,
result=result
)
db.add(record)
db.commit()
return AiResponse(
task_type=request.task_type,
prompt=request.prompt,
result=result
)
@app.get("/api/records")
def get_records(db: Session = Depends(get_db)):
records = db.query(AiRecord).order_by(AiRecord.id.desc()).limit(20).all()
return [
{
"id": item.id,
"task_type": item.task_type,
"prompt": item.prompt,
"result": item.result,
"created_at": str(item.created_at)
}
for item in records
]
8. backend/Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY app ./app
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
七、前端源码
前端使用 Vue 3 实现一个简单页面,包括任务类型选择、输入框、生成按钮和结果展示区域。
1. frontend/package.json
{
"name": "ai-office-frontend",
"version": "1.0.0",
"scripts": {
"dev": "vite --host 0.0.0.0",
"build": "vite build",
"preview": "vite preview --host 0.0.0.0"
},
"dependencies": {
"@vitejs/plugin-vue": "^5.0.5",
"axios": "^1.7.2",
"element-plus": "^2.7.6",
"vue": "^3.4.29"
},
"devDependencies": {
"vite": "^5.3.1"
}
}
2. frontend/index.html
AI办公助手
3. frontend/src/main.js
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
4. frontend/src/App.vue
AI办公助手
支持智能写作、文档总结、会议纪要整理等办公场景
生成内容
清空
生成结果
{{ result }}
最近记录
刷新
暂无记录
#{{ item.id }} {{ item.task_type }} - {{ item.created_at }}
输入:{{ item.prompt }}
输出:{{ item.result }}
5. frontend/nginx.conf
前端打包后通过 Nginx 提供静态资源,同时将 /api 请求反向代理到后端服务。
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
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;
}
}
6. frontend/Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json ./
RUN npm install --registry=https://registry.npmmirror.com
COPY . .
RUN npm run build
FROM nginx:1.25-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
八、环境变量配置
在项目根目录创建 .env 文件:
MYSQL_ROOT_PASSWORD=root_pass_123
MYSQL_DATABASE=ai_office
MYSQL_USER=ai_office
MYSQL_PASSWORD=ai_office_pass
AI_API_KEY=你的大模型API_KEY
AI_API_BASE=https://api.openai.com/v1
AI_MODEL=gpt-4o-mini
如果你使用的是其他大模型服务商,只需要修改:
AI_API_BASE=你的接口地址
AI_API_KEY=你的密钥
AI_MODEL=你的模型名称
例如某些兼容 OpenAI 格式的接口,一般也是:
https://xxx.example.com/v1
需要注意的是,本文的示例代码默认请求路径为:
/v1/chat/completions
因此 AI_API_BASE 不要写成完整的 /chat/completions 地址,否则会拼接错误。
九、Docker Compose 编排文件
在项目根目录创建 docker-compose.yml:
services:
mysql:
image: mysql:8.0
container_name: ai-office-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:7-alpine
container_name: ai-office-redis
restart: always
ports:
- "6379:6379"
backend:
build:
context: ./backend
container_name: ai-office-backend
restart: always
depends_on:
- mysql
- redis
environment:
MYSQL_HOST: mysql
MYSQL_PORT: 3306
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
AI_API_KEY: ${AI_API_KEY}
AI_API_BASE: ${AI_API_BASE}
AI_MODEL: ${AI_MODEL}
ports:
- "8000:8000"
frontend:
build:
context: ./frontend
container_name: ai-office-frontend
restart: always
depends_on:
- backend
ports:
- "80:80"
volumes:
mysql_data:
这个文件定义了四个服务:
mysql:数据库服务;redis:缓存服务,当前示例代码暂未深度使用,但实际项目常用于会话、限流、任务队列;backend:FastAPI后端;frontend:Vue前端 + Nginx。
十、一键构建并启动项目
在项目根目录执行:
docker compose up -d --build
等待镜像构建完成后,查看容器状态:
docker compose ps
如果看到类似结果,说明服务已经启动:
NAME STATUS
ai-office-mysql Up
ai-office-redis Up
ai-office-backend Up
ai-office-frontend Up
然后访问:
http://服务器IP
如果是本地部署,则访问:
http://localhost
后端接口也可以单独访问:
http://服务器IP:8000
返回如下内容说明后端正常:
{
"message": "AI Office API is running"
}
十一、常用运维命令
1. 查看日志
docker compose logs -f
查看某个服务日志:
docker compose logs -f backend
docker compose logs -f frontend
docker compose logs -f mysql
2. 停止服务
docker compose down
3. 停止并删除数据卷
如果你想连数据库数据一起删除,可以执行:
docker compose down -v
注意:这个命令会删除 MySQL 数据,请谨慎操作。
4. 重启服务
docker compose restart
重启单个服务:
docker compose restart backend
5. 重新构建后端
如果你修改了后端代码,可以执行:
docker compose up -d --build backend
6. 进入容器
docker exec -it ai-office-backend bash
MySQL 容器:
docker exec -it ai-office-mysql bash
十二、接口测试
1. 测试AI生成接口
可以使用 curl 测试:
curl -X POST http://localhost:8000/api/ai \
-H "Content-Type: application/json" \
-d '{
"task_type": "write",
"prompt": "帮我写一份关于AI办公系统上线的通知"
}'
正常情况下会返回:
{
"task_type": "write",
"prompt": "帮我写一份关于AI办公系统上线的通知",
"result": "..."
}
2. 查询最近记录
curl http://localhost:8000/api/records
十三、常见问题与解决方法
1. 后端启动失败,提示无法连接 MySQL
可能原因是 MySQL 第一次启动需要初始化,后端启动太快导致连接失败。可以等待十几秒后重启后端:
docker compose restart backend
更稳妥的方式是在后端启动脚本中加入数据库等待逻辑,或者在 Compose 中配置 healthcheck。
2. AI接口调用失败
请重点检查以下配置:
AI_API_KEY=是否正确
AI_API_BASE=是否正确
AI_MODEL=模型名称是否正确
还要确认服务器能访问对应API地址:
curl https://api.openai.com/v1/models
如果使用国内模型平台,请按照平台文档确认请求地址和模型名称。
3. 前端页面打不开
检查前端容器是否正常:
docker compose logs -f frontend
确认端口没有被占用:
sudo lsof -i:80
如果服务器80端口已经被占用,可以将 Compose 中前端端口改为:
ports:
- "8080:80"
然后访问:
http://服务器IP:8080
4. 前端请求后端接口失败
因为前端是通过 Nginx 代理 /api 请求到后端,所以需要确认 nginx.conf 中的服务名是否正确:
proxy_pass http://backend:8000/api/;
这里的 backend 必须和 docker-compose.yml 中的服务名一致。
5. 数据库中文乱码
本文已经在 MySQL 启动参数中设置了:
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
数据库连接字符串中也加入了:
charset=utf8mb4
如果仍然乱码,可以进入 MySQL 检查字符集:
SHOW VARIABLES LIKE 'character%';
十四、生产环境优化建议
上面的示例适合学习和中小规模内部部署。如果要用于生产环境,建议进一步优化。
1. 增加用户登录与权限控制
AI办公系统通常涉及公司文档、内部会议、业务数据等敏感内容,不能直接开放给所有人访问。可以增加:
- 用户注册登录;
- JWT Token认证;
- 角色权限控制;
- 部门级数据隔离;
- 操作日志审计。
2. 增加HTTPS证书
生产环境建议使用 HTTPS,可以通过 Nginx + Certbot 申请免费证书:
sudo apt install certbot python3-certbot-nginx
或者使用云厂商提供的证书服务。
3. 接入知识库
如果希望AI回答公司内部制度、产品文档、项目资料,可以增加知识库模块。常见方案包括:
- 文档上传;
- 文本切分;
- 向量化 Embedding;
- 向量数据库检索;
- RAG增强问答。
常见向量数据库有:
- Milvus;
- Qdrant;
- Weaviate;
- Elasticsearch;
- pgvector。
4. 增加异步任务队列
对于长文档总结、批量文档处理、会议录音转写等耗时任务,建议使用异步队列:
- Celery + Redis;
- RQ;
- Dramatiq;
- FastAPI BackgroundTasks。
这样可以避免接口长时间阻塞,提高系统稳定性。
5. 增加限流与费用控制
AI接口通常按Token计费,生产环境必须考虑成本控制:
- 单用户每日调用次数限制;
- 单次输入长度限制;
- 部门预算统计;
- 模型分级调用;
- 请求日志分析;
- 缓存重复问题答案。
6. 数据备份
MySQL 数据应定期备份,例如:
docker exec ai-office-mysql mysqldump \
-u root \
-p ai_office > ai_office_backup.sql
也可以结合定时任务自动备份到对象存储。
十五、扩展:增加本地大模型支持
如果公司对数据安全要求较高,不希望把办公内容发送到第三方API,可以部署本地大模型。例如使用 Ollama、vLLM、LM Studio 等工具。
以 Ollama 为例,启动本地模型服务后,后端可以将 AI_API_BASE 改为 Ollama 的兼容接口地址。如果部署在同一个 Docker 网络中,也可以将 Ollama 作为一个 Compose 服务加入。
示例:
ollama:
image: ollama/ollama
container_name: ai-office-ollama
restart: always
volumes:
- ollama_data:/root/.ollama
ports:
- "11434:11434"
然后根据 Ollama 的实际接口格式调整 ai_service.py。如果使用支持 OpenAI 兼容模式的本地服务,则改动会更少。
十六、总结
本文从零开始演示了一个 AI办公系统的 Docker 部署方案,包含后端 FastAPI、前端 Vue 3、MySQL、Redis、Nginx 以及 Docker Compose 编排文件。通过这种方式,可以避免手动安装各种语言环境和依赖,让部署过程更加标准化、可迁移、可维护。
本项目虽然是简化版,但已经具备AI办公系统的基本雏形:
- 可以通过页面输入办公需求;
- 可以调用大模型生成内容;
- 可以保存生成历史;
- 可以通过 Docker Compose 一键部署;
- 可以继续扩展用户系统、知识库、权限管理、异步任务等功能。
对于企业内部使用而言,建议在此基础上重点加强 权限控制、数据安全、日志审计、费用统计和私有化部署能力。如果只是个人学习或团队内部试用,本文提供的源码已经足够完成一次完整的AI办公应用部署实践。
最后,启动项目只需要记住一句命令:
docker compose up -d --build
访问浏览器:
http://服务器IP
即可开始使用你的 AI办公助手。