这个模板解决什么问题
做AI应用的人多半经历过这个阶段:前端跑起来了,后端API写好了,向量数据库也选好了,但要把它们跑在同一台机器上,配环境变量、搞网络、调端口,折腾半天就是跑不通。
这篇给你一个可以直接用的Docker Compose模板,包含Qdrant向量数据库、FastAPI后端、Next.js前端,一条命令启动整个AI应用开发环境。
这个模板解决什么问题
独立开发者搭AI应用,技术栈通常是这么几样:一个向量数据库做RAG检索,一个Python后端跑业务逻辑和LLM调用,一个前端框架做界面。每样都能单独跑,但放一起就各种问题:端口冲突、网络不通、数据不持久、环境变量散落各处。
Docker Compose把这些全收拢到一个文件里。你不需要记三套启动命令,不需要手动配网络,改完代码一条命令重启所有服务。
完整docker-compose.yml
直接复制改参数就能用:
version: "3.9"
services:
# 向量数据库 - Qdrant
qdrant:
image: qdrant/qdrant:latest
ports:
- "6333:6333" # REST API
- "6334:6334" # gRPC API
volumes:
- ./qdrant_data:/qdrant/storage
restart: unless-stopped
# 后端 - FastAPI
api:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
- QDRANT_URL=http://qdrant:6333
- OPENAI_API_KEY=${OPENAI_API_KEY}
- MODEL_NAME=gpt-4o-mini
volumes:
- ./backend:/app
depends_on:
- qdrant
restart: unless-stopped
# 前端 - Next.js
web:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8000
volumes:
- ./frontend:/app
- /app/node_modules
depends_on:
- api
restart: unless-stopped
后端Dockerfile
FastAPI后端的Dockerfile,用Python 3.12 slim镜像,装依赖跑dev server:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
对应的requirements.txt:
fastapi==0.115.0
uvicorn[standard]==0.32.0
openai==1.54.0
qdrant-client==1.12.0
python-dotenv==1.0.1
前端Dockerfile
Next.js前端,用node 22 alpine镜像:
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["npm", "run", "dev"]
项目目录结构
my-ai-app/
├── docker-compose.yml
├── .env # 放 OPENAI_API_KEY=sk-xxx
├── qdrant_data/ # Qdrant自动创建
├── backend/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── main.py
└── frontend/
├── Dockerfile
├── package.json
└── ...
一条命令启动
在项目根目录放好.env文件,写入你的OpenAI API Key,然后:
docker compose up --build
三个服务同时启动。Qdrant的Web UI在 localhost:6333/dashboard,FastAPI的文档在 localhost:8000/docs,前端在 localhost:3000。
后端main.py最小可用示例
这段代码连通了Qdrant和OpenAI,能做最基础的RAG问答:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from openai import OpenAI
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams
import os
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["*"],
allow_headers=["*"],
)
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
qdrant = QdrantClient(url=os.getenv("QDRANT_URL", "http://localhost:6333"))
COLLECTION = "docs"
@app.on_event("startup")
async def startup():
collections = qdrant.get_collections().collections
if not any(c.name == COLLECTION for c in collections):
qdrant.create_collection(
collection_name=COLLECTION,
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)
@app.post("/search")
async def search(query: str):
embedding = client.embeddings.create(
input=query,
model="text-embedding-3-small"
).data[0].embedding
results = qdrant.search(
collection_name=COLLECTION,
query_vector=embedding,
limit=5
)
return {"results": results}
这里用的text-embedding-3-small模型,1536维度,跟Qdrant collection的size对应。text-embedding-3-small的定价是$0.02每百万token,做开发测试基本可以忽略成本。这个价格来自OpenAI官方定价页面。
几个实际使用建议
端口冲突处理。 如果本地已经跑了别的服务占用6333或3000,改docker-compose.yml里的端口映射就行。左边是宿主机端口,右边是容器端口,只改左边的。
数据持久化。 Qdrant的数据存在./qdrant_data目录里。这个目录是Docker自动创建的,删掉容器数据不会丢。要彻底重置,删掉这个目录再重启。
API Key安全。 别把OpenAI API Key写进docker-compose.yml里。用.env文件管理,Docker Compose会自动读取。记得把.env加到.gitignore。
生产部署。 这个模板是开发环境用的,uvicorn带–reload,Next.js用dev模式。上生产的话,后端换gunicorn,前端跑npm run build再start,Qdrant可以考虑用Qdrant Cloud的免费tier。
为什么选Qdrant不选Pinecone
这个模板选Qdrant做向量数据库,原因很实际:Qdrant开源,Docker一键跑,本地开发零成本。Qdrant官方文档给的Quickstart就是Docker方式,docker pull qdrant/qdrant然后docker run,非常简单。
Pinecone是托管服务,本地开发也得连远程,免费tier有限制。对独立开发者来说,能用本地服务搞定的事情,没必要多依赖一个云服务。等应用上线了需要扩展,再迁到Qdrant Cloud或者Pinecone都行。
模板扩展方向
这个模板跑起来之后,可以往几个方向加东西:
在backend里加一个文档上传接口,接收PDF或文本文件,切片后用OpenAI Embedding向量化存到Qdrant。在frontend里加一个聊天界面,调backend的search接口拿相关文档,拼进Prompt发给OpenAI做问答。在docker-compose.yml里加一个Redis服务做缓存,高频问题的答案存进去省API费用。
模板的意义不是一步到位,是从80分开始往上加。先跑通最小闭环,再迭代。
验证清单
模板跑起来后检查这几个点:Qdrant的dashboard能不能访问、FastAPI的/docs文档能不能打开、前端能不能调通后端API、改后端代码uvicorn是否自动重载、改前端代码Next.js是否热更新。这些都通了,说明开发环境没问题,可以开始写业务逻辑了。
