从零搭建一套可私有化部署的 AI 办公助手:Docker 一键上线+完整源码
AI办公 Docker部署教程|附源码
随着大语言模型(LLM)能力的不断提升,越来越多企业和个人开始把 AI 引入日常办公场景,例如:文档摘要、会议纪要生成、邮件润色、PPT 大纲生成、Excel 数据分析、知识库问答等。相比直接使用公开 AI 工具,自建一套“AI办公助手”有几个明显优势:数据可控、可接入企业内部知识库、可按需扩展功能、部署成本可控,并且能够结合公司业务进行二次开发。
本文将带你从零搭建一个简易版 AI办公系统,并使用 Docker + Docker Compose 完成一键部署。项目包含前端页面、后端 API 服务、数据库服务,并预留大模型接口配置。文章会提供完整目录结构、核心源码、Dockerfile、docker-compose.yml 以及部署步骤,适合学习、二次开发和企业内部原型验证。
一、项目功能介绍
本教程实现的是一个轻量级 AI办公助手,主要包含以下功能:
-
AI 对话办公助手
- 支持输入办公需求,例如“帮我写一封请假邮件”“总结下面这段文档内容”。
- 后端调用大模型接口返回结果。
-
文档摘要
- 用户输入一段较长文本。
- AI 自动生成摘要、重点和待办事项。
-
邮件润色
- 将普通表达转换为正式、礼貌、商务风格的邮件内容。
-
会议纪要生成
- 根据会议记录生成结构化纪要,包括会议主题、参会人员、重点结论、待办事项。
-
历史记录保存
- 使用 MySQL 存储用户请求和 AI 返回内容。
- 便于后续查看和统计。
-
Docker 一键部署
- 前端、后端、数据库统一编排。
- 适合部署到本地服务器、云服务器或内网环境。
二、技术栈说明
本项目采用前后端分离架构:
| 模块 | 技术 |
|---|---|
| 前端 | Vue 3 + Vite |
| 后端 | Node.js + Express |
| 数据库 | MySQL 8 |
| 部署 | Docker + Docker Compose |
| AI接口 | OpenAI兼容接口 / 私有大模型接口 |
整体架构如下:
用户浏览器
│
▼
前端 Vue 页面
│ HTTP请求
▼
后端 Express API
│
├── 调用大模型接口
│
└── 写入 MySQL 数据库
三、项目目录结构
创建项目目录:
mkdir ai-office-docker
cd ai-office-docker
推荐目录结构如下:
ai-office-docker
├── backend
│ ├── Dockerfile
│ ├── package.json
│ ├── server.js
│ └── .env.example
├── frontend
│ ├── Dockerfile
│ ├── nginx.conf
│ ├── package.json
│ ├── index.html
│ └── src
│ ├── App.vue
│ └── main.js
├── mysql
│ └── init.sql
└── docker-compose.yml
四、后端源码编写
后端主要负责三件事:
- 接收前端请求;
- 调用 AI 大模型接口;
- 保存请求历史记录到数据库。
进入后端目录:
mkdir backend
cd backend
1. 创建 package.json
{
"name": "ai-office-backend",
"version": "1.0.0",
"description": "AI Office Backend API",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"axios": "^1.6.8",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.3",
"mysql2": "^3.9.2"
}
}
2. 创建环境变量示例文件
文件名:backend/.env.example
PORT=3000
DB_HOST=mysql
DB_PORT=3306
DB_USER=root
DB_PASSWORD=123456
DB_NAME=ai_office
AI_API_KEY=your_api_key
AI_BASE_URL=https://api.openai.com/v1/chat/completions
AI_MODEL=gpt-4o-mini
说明:
AI_API_KEY:填写你的大模型 API Key。AI_BASE_URL:如果你使用的是兼容 OpenAI 格式的国产模型,也可以填写对应接口地址。AI_MODEL:模型名称,可根据服务商要求修改。
3. 创建 server.js
文件名:backend/server.js
const express = require("express");
const cors = require("cors");
const axios = require("axios");
const mysql = require("mysql2/promise");
require("dotenv").config();
const app = express();
app.use(cors());
app.use(express.json({ limit: "5mb" }));
const PORT = process.env.PORT || 3000;
const dbConfig = {
host: process.env.DB_HOST || "mysql",
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER || "root",
password: process.env.DB_PASSWORD || "123456",
database: process.env.DB_NAME || "ai_office",
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
};
const pool = mysql.createPool(dbConfig);
function buildPrompt(type, content) {
const prompts = {
chat: `你是一名专业的AI办公助手,请根据用户需求提供清晰、实用、结构化的回答。用户内容如下:\n${content}`,
summary: `请将以下文本整理为办公摘要,要求包含:1.核心摘要;2.重点事项;3.待办清单。\n文本内容:\n${content}`,
email: `请将以下内容润色为正式、礼貌、商务风格的邮件,要求语气自然、表达清晰。\n原始内容:\n${content}`,
meeting: `请根据以下会议记录生成会议纪要,要求包含:会议主题、会议结论、关键讨论点、待办事项、责任人建议。\n会议记录:\n${content}`
};
return prompts[type] || prompts.chat;
}
async function callAI(prompt) {
const apiKey = process.env.AI_API_KEY;
const baseURL = process.env.AI_BASE_URL;
const model = process.env.AI_MODEL || "gpt-4o-mini";
if (!apiKey) {
return "当前未配置 AI_API_KEY,请在 docker-compose.yml 或 .env 文件中配置大模型接口密钥。";
}
const response = await axios.post(
baseURL,
{
model,
messages: [
{
role: "system",
content: "你是一个擅长企业办公、文档处理、会议纪要和商务沟通的AI助手。"
},
{
role: "user",
content: prompt
}
],
temperature: 0.7
},
{
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
timeout: 60000
}
);
return response.data.choices?.[0]?.message?.content || "AI未返回有效内容。";
}
async function saveHistory(type, input, output) {
const sql = `
INSERT INTO histories(type, input_text, output_text)
VALUES (?, ?, ?)
`;
await pool.execute(sql, [type, input, output]);
}
app.get("/api/health", async (req, res) => {
res.json({
status: "ok",
message: "AI Office Backend is running"
});
});
app.post("/api/ai", async (req, res) => {
try {
const { type, content } = req.body;
if (!content || !content.trim()) {
return res.status(400).json({
success: false,
message: "内容不能为空"
});
}
const prompt = buildPrompt(type, content);
const result = await callAI(prompt);
await saveHistory(type || "chat", content, result);
res.json({
success: true,
data: result
});
} catch (error) {
console.error("AI处理失败:", error.message);
res.status(500).json({
success: false,
message: "AI处理失败,请检查接口配置或网络连接",
error: error.message
});
}
});
app.get("/api/histories", async (req, res) => {
try {
const [rows] = await pool.query(`
SELECT id, type, input_text, output_text, created_at
FROM histories
ORDER BY id DESC
LIMIT 20
`);
res.json({
success: true,
data: rows
});
} catch (error) {
res.status(500).json({
success: false,
message: "查询历史记录失败",
error: error.message
});
}
});
app.listen(PORT, () => {
console.log(`AI Office Backend running on port ${PORT}`);
});
4. 后端 Dockerfile
文件名:backend/Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package.json ./
RUN npm install --registry=https://registry.npmmirror.com
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
五、数据库初始化脚本
回到项目根目录,创建 MySQL 初始化目录:
mkdir mysql
创建文件:mysql/init.sql
CREATE DATABASE IF NOT EXISTS ai_office
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE ai_office;
CREATE TABLE IF NOT EXISTS histories (
id INT AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50) NOT NULL COMMENT '功能类型:chat/summary/email/meeting',
input_text LONGTEXT NOT NULL COMMENT '用户输入内容',
output_text LONGTEXT NOT NULL COMMENT 'AI输出内容',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这个表用于保存用户的输入内容和 AI 返回结果。实际生产环境中,可以继续扩展用户表、权限表、知识库表、文件上传表等。
六、前端源码编写
前端使用 Vue 3 + Vite,实现一个简单清爽的办公助手页面。用户可以选择功能类型,输入内容,然后点击生成。
进入前端目录:
mkdir frontend
cd frontend
1. 创建 package.json
文件名:frontend/package.json
{
"name": "ai-office-frontend",
"version": "1.0.0",
"description": "AI Office Frontend",
"scripts": {
"dev": "vite --host 0.0.0.0",
"build": "vite build"
},
"dependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"vite": "^5.1.6",
"vue": "^3.4.21"
},
"devDependencies": {}
}
2. 创建 index.html
文件名:frontend/index.html
AI办公助手
3. 创建 main.js
创建目录:
mkdir src
文件名:frontend/src/main.js
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
4. 创建 App.vue
文件名:frontend/src/App.vue
AI办公助手
支持文档摘要、邮件润色、会议纪要和通用办公问答
AI生成结果
{{ result }}
生成结果将在这里展示
最近历史记录
暂无历史记录
输入:{{ item.input_text }}
输出:{{ item.output_text }}
5. 前端 Nginx 配置
由于前端构建后是静态文件,我们使用 Nginx 托管,同时将 /api 请求反向代理到后端服务。
文件名:frontend/nginx.conf
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:3000/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. 前端 Dockerfile
文件名: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
CMD ["nginx", "-g", "daemon off;"]
七、Docker Compose 编排
回到项目根目录,创建 docker-compose.yml:
version: "3.8"
services:
mysql:
image: mysql:8.0
container_name: ai-office-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: ai_office
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- ai-office-net
backend:
build:
context: ./backend
container_name: ai-office-backend
restart: always
depends_on:
- mysql
environment:
PORT: 3000
DB_HOST: mysql
DB_PORT: 3306
DB_USER: root
DB_PASSWORD: 123456
DB_NAME: ai_office
AI_API_KEY: your_api_key
AI_BASE_URL: https://api.openai.com/v1/chat/completions
AI_MODEL: gpt-4o-mini
ports:
- "3000:3000"
networks:
- ai-office-net
frontend:
build:
context: ./frontend
container_name: ai-office-frontend
restart: always
depends_on:
- backend
ports:
- "8080:80"
networks:
- ai-office-net
volumes:
mysql_data:
networks:
ai-office-net:
driver: bridge
注意:请将
AI_API_KEY: your_api_key替换成你自己的大模型接口密钥。如果你使用的是私有化模型接口,例如企业内部部署的 Qwen、DeepSeek、GLM、Llama 等,只要接口兼容 OpenAI Chat Completions 格式,就可以直接替换AI_BASE_URL和AI_MODEL。
八、启动部署
在项目根目录执行:
docker compose up -d --build
如果你的 Docker 版本较旧,也可能需要使用:
docker-compose up -d --build
查看容器状态:
docker ps
正常情况下可以看到三个容器:
ai-office-mysql
ai-office-backend
ai-office-frontend
查看后端日志:
docker logs -f ai-office-backend
查看前端日志:
docker logs -f ai-office-frontend
访问系统:
http://服务器IP:8080
如果是本地部署,可以访问:
http://localhost:8080
九、接口测试
除了通过前端页面访问,也可以使用 curl 测试后端接口。
1. 健康检查
curl http://localhost:3000/api/health
返回示例:
{
"status": "ok",
"message": "AI Office Backend is running"
}
2. AI 办公生成接口
curl -X POST http://localhost:3000/api/ai \
-H "Content-Type: application/json" \
-d '{
"type": "email",
"content": "通知客户项目因为供应商原因要延期一周,希望客户理解"
}'
返回示例:
{
"success": true,
"data": "尊敬的客户您好:\n\n非常感谢您一直以来对我们项目工作的支持..."
}
3. 查询历史记录
curl http://localhost:3000/api/histories
十、常见问题与解决方法
1. 前端页面能打开,但 AI 请求失败
可能原因:
- 后端服务未启动;
- Nginx 反向代理配置错误;
- 后端接口地址不正确;
- 大模型 API Key 未配置;
- 服务器无法访问外部 AI 接口。
解决方法:
docker logs -f ai-office-backend
查看后端日志,根据错误信息定位问题。
2. MySQL 连接失败
后端启动时如果出现类似错误:
ECONNREFUSED
Access denied for user
Unknown database
可以检查:
docker-compose.yml中数据库密码是否一致;- MySQL 容器是否正常启动;
- 初始化 SQL 是否执行成功;
- 后端连接地址是否写成了
mysql,而不是localhost。
在 Docker Compose 网络中,服务之间通过服务名访问,所以后端连接 MySQL 的地址应该是:
mysql
而不是:
127.0.0.1
3. 修改代码后不生效
如果你修改了前端或后端源码,需要重新构建镜像:
docker compose up -d --build
如果需要彻底清理旧容器和数据:
docker compose down
docker compose up -d --build
如果连 MySQL 数据也要删除:
docker compose down -v
docker compose up -d --build
注意:-v 会删除数据库卷,历史记录会丢失。
4. 端口冲突
如果本机已经占用了 8080、3000 或 3306,可以修改 docker-compose.yml 中左侧端口。
例如将前端端口改为 8090:
ports:
- "8090:80"
访问地址改为:
http://localhost:8090
十一、生产环境优化建议
上面的代码适合学习和原型验证。如果要用于企业生产环境,建议进一步优化。
1. 增加用户登录与权限控制
当前示例没有用户体系,任何访问页面的人都可以调用 AI 接口。生产环境中应增加:
- 用户注册与登录;
- JWT 鉴权;
- 角色权限控制;
- 管理员后台;
- 调用次数限制。
2. 增加接口限流
AI 接口通常按 Token 计费,如果没有限流,容易出现滥用问题。可以使用:
- Nginx 限流;
- Redis 记录用户调用次数;
- 后端中间件限流;
- 按部门或用户设置额度。
3. 增加敏感词和数据脱敏
企业办公场景可能包含客户信息、合同信息、财务数据等敏感内容。建议在调用大模型前做数据脱敏,例如:
- 手机号脱敏;
- 邮箱脱敏;
- 身份证号脱敏;
- 客户名称替换;
- 合同编号替换。
4. 接入知识库
如果希望 AI 回答企业内部制度、产品文档、技术手册等内容,可以扩展知识库模块:
- 文件上传;
- 文档切分;
- 向量化;
- 向量数据库检索;
- RAG 增强生成。
常见向量数据库包括:
- Milvus;
- Qdrant;
- Weaviate;
- Elasticsearch;
- pgvector。
5. 支持本地大模型
如果企业对数据安全要求较高,可以使用本地模型:
- Qwen;
- DeepSeek;
- GLM;
- Llama;
- Baichuan;
- Yi。
部署方式可以选择 Ollama、vLLM、LMDeploy 或 Text Generation Inference。只要服务提供 OpenAI 兼容接口,本文后端代码基本无需大改。
十二、项目扩展方向
这个 AI办公系统只是基础版本,你可以继续扩展为更完整的办公平台。
1. Word 文档处理
支持上传 Word 文档,然后自动生成:
- 文档摘要;
- 风险点;
- 修改建议;
- 汇报材料;
- 领导版简报。
2. Excel 数据分析
支持上传 Excel 表格,让 AI 自动分析:
- 销售趋势;
- 异常数据;
- 关键指标;
- 可视化图表建议;
- 经营分析结论。
3. PPT 大纲生成
输入主题后自动生成:
- PPT 标题;
- 页目录;
- 每页核心内容;
- 演讲稿;
- 视觉风格建议。
4. 企业知识库问答
把公司制度、产品说明、技术文档、客服 FAQ 导入知识库,员工可以直接提问,例如:
公司年假制度是什么?
某产品的售后流程是什么?
服务器上线审批需要哪些材料?
AI 根据内部文档回答,而不是凭空生成。
5. 多模型切换
可以在后台增加模型配置功能,让用户选择不同模型:
- 通用模型;
- 代码模型;
- 文档模型;
- 本地私有模型;
- 多模态模型。
十三、安全注意事项
部署 AI办公系统时,不要只关注功能,还要重视安全。
-
不要把 API Key 写进前端代码
- 前端代码会暴露给浏览器。
- API Key 必须放在后端环境变量中。
-
不要在公网直接暴露数据库端口
- 示例中暴露了
3306便于调试。 - 生产环境建议删除 MySQL 的 ports 映射,只允许容器内部访问。
- 示例中暴露了
-
开启 HTTPS
- 如果部署到公网,建议通过 Nginx、Caddy 或云厂商证书开启 HTTPS。
-
限制上传文件大小
- 如果后续增加文件上传,应限制文件大小和类型。
-
记录调用日志
- 保存调用用户、时间、消耗 Token、请求类型,便于审计和成本分析。
十四、完整部署命令汇总
如果你已经按照上文创建好全部文件,可以直接执行以下命令:
cd ai-office-docker
docker compose up -d --build
docker ps
访问:
http://localhost:8080
停止服务:
docker compose down
停止并删除数据库数据:
docker compose down -v
重新构建:
docker compose up -d --build
十五、总结
本文从零实现并部署了一个简易版 AI办公助手系统,包含前端 Vue 页面、后端 Express API、MySQL 数据库和 Docker Compose 一键编排。通过这个项目,你可以快速理解 AI办公类应用的基本架构:前端负责交互,后端负责封装大模型调用,数据库负责保存业务数据,Docker 负责统一部署和环境隔离。
这个项目虽然简单,但具备较好的扩展基础。你可以在此基础上继续加入用户系统、知识库问答、文件上传、Excel 分析、PPT 生成、多模型切换、企业权限管理等功能,逐步演进为真正适合企业内部使用的 AI办公平台。
对于个人开发者来说,它是一个很好的 AI 应用练手项目;对于企业技术团队来说,它也可以作为内部 AI 工具平台的原型。只要继续完善安全、权限、日志、成本控制和知识库能力,就能让 AI 真正融入日常办公流程,提高文档处理、沟通协作和信息整理效率。