You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.0 KiB
8.0 KiB
Docker 容器化开发环境实施计划
目标: 在 Docker 容器内运行 FastAPI,使用 asyncpg 驱动,解决 macOS GSSAPI 问题
预计时间: 30 分钟
状态: 待执行
创建时间: 2026-01-17
背景
问题
- macOS 上 asyncpg 存在 GSSAPI 认证问题
- 无法直接连接 PostgreSQL("role postgres does not exist" 错误)
- 已尝试多种方案均无效
解决方案
在 Docker 容器内运行 FastAPI,完全避免 macOS 环境问题,同时保留 asyncpg 的性能优势(比 psycopg 快 2.8 倍)。
实施步骤
Step 1: 恢复 asyncpg 依赖
文件: server/requirements.txt
操作:
# 数据库驱动(使用 asyncpg 获得最佳性能)
asyncpg==0.29.0
说明: 移除 psycopg,恢复 asyncpg
Step 2: 恢复数据库连接配置
文件: server/.env
操作:
# 数据库配置(容器内网络)
DATABASE_URL=postgresql+asyncpg://postgres:postgres@postgres:5432/jointo
DATABASE_ECHO=True
说明:
- 使用容器名称
postgres作为主机名(Docker 内部 DNS) - 不再使用 127.0.0.1(宿主机地址)
文件: server/app/core/database.py
操作:
# 创建异步引擎
engine = create_async_engine(
settings.DATABASE_URL,
echo=settings.DATABASE_ECHO,
future=True,
pool_pre_ping=True,
pool_size=10,
max_overflow=20
)
说明: 移除 connect_args(容器内不需要禁用 GSSAPI)
Step 3: 优化 Dockerfile(支持热重载)
文件: server/Dockerfile
操作:
FROM python:3.11-slim
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
gcc \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY requirements.txt .
# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码(开发模式下会被挂载覆盖)
COPY . .
# 暴露端口
EXPOSE 8000
# 启动命令(支持热重载)
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
关键点:
- 使用 Python 3.11(与本地一致)
- 安装 gcc(编译 asyncpg C 扩展)
--reload支持代码热重载
Step 4: 更新 docker-compose.yml
文件: server/docker-compose.yml
操作: 添加 app 服务
version: "3.8"
services:
# PostgreSQL 数据库
postgres:
image: postgres:14-alpine
container_name: jointo-server-postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: jointo
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- jointo-network
# Redis 缓存
redis:
image: redis:7-alpine
container_name: jointo-server-redis
ports:
- "6381:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- jointo-network
# MinIO 对象存储
minio:
image: minio/minio:latest
container_name: jointo-server-minio
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9100:9000"
- "9101:9001"
volumes:
- minio_data:/data
command: server /data --console-address ":9001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
networks:
- jointo-network
# FastAPI 应用(新增)
app:
build:
context: .
dockerfile: Dockerfile
container_name: jointo-server-app
ports:
- "8000:8000"
volumes:
- .:/app # 挂载代码目录(支持热重载)
- /app/venv # 排除虚拟环境
environment:
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@postgres:5432/jointo
- REDIS_URL=redis://redis:6379/0
- MINIO_ENDPOINT=minio:9000
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
networks:
- jointo-network
restart: unless-stopped
volumes:
postgres_data:
redis_data:
minio_data:
networks:
jointo-network:
driver: bridge
关键配置:
volumes: - .:/app- 挂载代码目录,支持热重载depends_on- 等待数据库服务健康后再启动networks- 所有服务在同一网络,可通过服务名互相访问
Step 5: 创建 .dockerignore
文件: server/.dockerignore
操作:
venv/
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.so
*.egg
*.egg-info/
dist/
build/
.pytest_cache/
.coverage
htmlcov/
.env
.DS_Store
*.log
说明: 避免将不必要的文件复制到镜像中
Step 6: 更新启动脚本
文件: server/start_docker.sh(新建)
操作:
#!/bin/bash
# 停止并移除旧容器
docker-compose down
# 构建并启动所有服务
docker-compose up --build -d
# 查看日志
docker-compose logs -f app
说明: 简化 Docker 启动流程
Step 7: 更新 README.md
文件: server/README.md
操作: 添加 Docker 开发指南
## 开发环境
### 方式 1: Docker 容器(推荐)
**优点**: 环境一致,性能最优(使用 asyncpg)
```bash
# 启动所有服务
docker-compose up --build -d
# 查看日志
docker-compose logs -f app
# 停止服务
docker-compose down
```
访问:
- API 文档: http://localhost:8000/api/docs
- 健康检查: http://localhost:8000/health
方式 2: 本地运行(仅限 Linux)
macOS 用户请使用 Docker 方式,避免 asyncpg GSSAPI 问题。
# 启动依赖服务
docker-compose up -d postgres redis minio
# 本地运行 FastAPI
./start_dev.sh
---
## 验证步骤
### 1. 构建并启动服务
```bash
cd server
docker-compose up --build -d
2. 检查容器状态
docker-compose ps
预期输出:
NAME STATUS
jointo-server-app Up (healthy)
jointo-server-postgres Up (healthy)
jointo-server-redis Up (healthy)
jointo-server-minio Up (healthy)
3. 查看应用日志
docker-compose logs -f app
预期输出:
🚀 Starting Jointo API...
✅ Database initialized
INFO: Uvicorn running on http://0.0.0.0:8000
4. 测试 API 端点
# 健康检查
curl http://localhost:8000/health
# 数据库健康检查
curl http://localhost:8000/api/v1/health/db
# API 文档
open http://localhost:8000/api/docs
5. 测试热重载
修改 app/main.py 中的任意代码,保存后观察日志:
INFO: Detected file change, reloading...
预期结果
✅ FastAPI 在 Docker 容器内成功启动
✅ asyncpg 正常连接 PostgreSQL
✅ 数据库表自动创建
✅ 代码修改自动热重载
✅ 所有健康检查端点正常响应
回滚方案
如果遇到问题,可以快速回滚:
# 停止 Docker 服务
docker-compose down
# 使用本地 + psycopg 方案
# 1. 修改 requirements.txt: asyncpg -> psycopg[binary]
# 2. 修改 .env: postgresql+asyncpg -> postgresql+psycopg
# 3. 重新安装依赖
# 4. 启动本地服务
相关文件
server/Dockerfile- 应用镜像定义server/docker-compose.yml- 服务编排配置server/.dockerignore- Docker 忽略文件server/start_docker.sh- 启动脚本server/requirements.txt- Python 依赖server/.env- 环境变量配置server/README.md- 项目文档
后续优化
- 多阶段构建: 减小镜像体积
- 健康检查: 为 app 服务添加健康检查
- 日志管理: 配置日志收集和轮转
- 性能监控: 集成 Prometheus + Grafana
- 调试支持: 配置远程调试器
更新日志
- 2026-01-17: 初始版本,实施 Docker 容器化开发环境