本文档记录后端 FastAPI 服务的免费/低成本 Docker 部署方案。目标是先在没有自有服务器的情况下跑通 demo,后续如果迁到 VPS / Oracle Cloud / Fly.io,仍复用同一套 Dockerfile。
Backend FastAPI -> Render Free Web Service 或 Koyeb Free
PostgreSQL -> Supabase Free 或 Neon Free,需要 pgvector
Redis -> Upstash Redis Free
LLM Provider -> OpenAI-compatible / OpenRouter / Ollama Cloud
Frontend -> Vercel Hobby 或 websites Docker standalone
不建议在免费容器平台里跑本地 Ollama 模型。模型下载、磁盘、内存、推理算力都不适合白嫖平台。
Dockerfile
.dockerignore
deploy/backend/entrypoint.sh
deploy/backend/render.yaml
容器启动入口:
uv run uvicorn api.app:create_app --factory --host 0.0.0.0 --port ${PORT:-8000}默认启动前会执行:
uv run alembic upgrade head如需关闭自动迁移,设置:
RUN_MIGRATIONS=false- 打开
https://render.com。 - 连接 GitHub 仓库。
- 创建
Web Service。 - Runtime 选择
Docker。 - Dockerfile 使用仓库根目录的
Dockerfile。 - Plan 选择
Free。 - Health Check Path 填:
/health
也可以使用 deploy/backend/render.yaml 作为 Blueprint 模板。
Render/Koyeb/Fly 平台里配置:
APP_ENV=prod
LOG_LEVEL=INFO
RUN_MIGRATIONS=true
JWT_SECRET=<强随机字符串>
PROVIDER_ENCRYPTION_KEY=<Fernet key>
DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@HOST:PORT/DB
REDIS_URL=rediss://...
APP_CORS_ORIGINS=https://你的前端域名
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_API_KEY=<你的 key>
OPENAI_CHAT_MODEL=gpt-4o-mini
OPENAI_EMBED_MODEL=text-embedding-3-small
STORAGE_BACKEND=s3
S3_ENDPOINT_URL=https://你的-minio-api
S3_PUBLIC_ENDPOINT_URL=https://你的-minio-api
S3_ACCESS_KEY=<MinIO access key>
S3_SECRET_KEY=<MinIO secret key>
S3_BUCKET=rag-assets
S3_REGION=us-east-1如果用 OpenRouter:
OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_API_KEY=<OpenRouter key>
OPENAI_CHAT_MODEL=<模型名>注意:OpenRouter/Groq 等平台不一定提供 embedding。RAG 需要确保 OPENAI_EMBED_MODEL 对应 endpoint 可用。
JWT secret:
openssl rand -hex 32Fernet key,无需额外安装 cryptography:
python3 -c "import os, base64; print(base64.urlsafe_b64encode(os.urandom(32)).decode())"也可以在已安装项目依赖的虚拟环境中使用:
uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"参考:
deploy/backend/.env.production.example
真实值应填写到部署平台的 Environment Variables / Secrets 页面,不要提交到 Git。
- 打开
https://supabase.com。 - 创建 project。
- 在 SQL Editor 执行:
create extension if not exists vector;- 复制 Postgres connection string。
- 改成 SQLAlchemy async URL:
postgresql+asyncpg://USER:PASSWORD@HOST:PORT/DB
Neon 作为免费 Postgres 时建议使用 Direct connection,先避免 pooled/PgBouncer 与 asyncpg prepared statements 的兼容坑。
- 打开 Neon Console。
- 进入项目的 Connection Details。
- 选择 Direct connection。
- 复制 connection string,例如:
postgresql://USER:PASSWORD@HOST/DB?sslmode=require
- 改成 SQLAlchemy async URL:
postgresql+asyncpg://USER:PASSWORD@HOST/DB?sslmode=require
如果使用 Neon pooler 地址(host 中包含 -pooler),建议加上:
prepared_statement_cache_size=0
最终类似:
postgresql+asyncpg://USER:PASSWORD@HOST/DB?sslmode=require&prepared_statement_cache_size=0
项目会在运行时把 sslmode=require 转换为 asyncpg 的 SSL connect args,因此部署平台里可以保留 Neon 默认的 sslmode=require。
- 在 Neon SQL Editor 执行:
CREATE EXTENSION IF NOT EXISTS vector;推荐 Upstash:
- 打开
https://upstash.com。 - 创建 Redis database。
- 复制
REDIS_URL。 - 优先使用 TLS URL:
rediss://...
已提供:
.github/workflows/deploy-hf-backend.yml
触发条件:
push 到 master
手动 workflow_dispatch
GitHub 仓库需要配置 secret:
Settings -> Secrets and variables -> Actions -> New repository secret
HF_TOKEN=<Hugging Face write token>
Token 创建位置:
https://huggingface.co/settings/tokens
权限需要 Write。workflow 会执行:
git push https://huggingface.co/spaces/luhanxin/rag-chat-backend HEAD:main注意:当前 workflow 使用普通 push,不强制覆盖 HF Space 历史。合入 master 时建议使用 merge commit,不要 squash 掉包含 HF initial commit 的历史;如果未来确定要把 HF Space 当纯部署镜像,可再改为 --force-with-lease。
docker build -t rag-ai-backend .
docker run --rm -p 8000:8000 \
--env-file .env \
-e RUN_MIGRATIONS=false \
rag-ai-backend访问:
http://localhost:8000/health
当前容器入口为了 demo 简化,默认启动前自动迁移。后续生产化建议:
- 将 migration 改成 release command/job。
- 为 worker 单独拆镜像或进程。
- 对 SSE / WebSocket 设置平台超时策略。
- 根据免费平台休眠行为增加前端错误提示和重试。