
本文介绍如何通过共享 python 包方式,让 telegram 机器人和 web 小程序两个独立容器安全、高效地复用同一份 postgresql 访问逻辑(database.py),避免代码重复,同时保持容器职责分离与可维护性。
本文介绍如何通过共享 python 包方式,让 telegram 机器人和 web 小程序两个独立容器安全、高效地复用同一份 postgresql 访问逻辑(database.py),避免代码重复,同时保持容器职责分离与可维护性。
在微服务或模块化部署实践中,将 Telegram Bot 和 Mini App(如基于 Flask/FastAPI 的 Web 小程序)拆分为独立容器是推荐做法:Bot 专注消息轮询与响应,App 专注 HTTP 接口与前端交互,二者共用同一 PostgreSQL 数据库但运行环境隔离。此时,核心挑战并非“能否共享代码”,而是“如何安全、可维护地共享”。
✅ 正确解法:将 database.py 提炼为跨服务的公共 Python 包,而非复制文件或挂载宿主机路径(后者破坏容器不可变性与环境一致性)。
? 目录结构设计(推荐)
project-root/
├── bot/ # Telegram Bot 源码(含 main.py、handlers/ 等)
├── app/ # Web 小程序源码(如 app/main.py、routes/ 等)
└── common/
└── database/
├── __init__.py
└── database.py # 封装连接池、CRUD 方法、上下文管理等
✨ 关键设计点:
common/database/__init__.py显式导出接口,例如:# common/database/__init__.py from .database import DatabaseManager, get_db_session __all__ = ["DatabaseManager", "get_db_session"]- 这样调用方只需
from database import DatabaseManager,无需关心内部路径,便于未来重构。
? Docker 构建配置(关键!)
两个服务需分别 COPY 公共模块 + 设置 PYTHONPATH,确保导入路径一致:
Bot 的 Dockerfile 片段:
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制共享模块(非挂载!保证镜像自包含) COPY ./common /common # 复制自身代码 COPY ./bot /bot # 使 Python 同时识别 /bot 和 /common 下的模块 ENV PYTHONPATH=/bot:/common CMD ["python", "/bot/main.py"]
App 的 Dockerfile 片段:
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 同样复制 common,但自身代码路径不同 COPY ./common /common COPY ./app /app # PYTHONPATH 适配:/app 优先于 /common,避免命名冲突 ENV PYTHONPATH=/app:/common CMD ["gunicorn", "-b :8000", "app.main:app"]
? 在代码中使用共享模块
- Bot 中调用:
# bot/handlers/user.py from database import DatabaseManager db = DatabaseManager("postgresql://user:pass@db:5432/botdb") user = db.get_user(123) - App 中调用:
# app/routes/api.py from database import get_db_session with get_db_session() as session: user = session.query(User).filter_by(id=123).first()
⚠️ 注意事项与最佳实践
-
禁止直接挂载
./common到容器(如-v $(pwd)/common:/common):这会导致开发环境与生产镜像行为不一致,且违反“构建一次,随处运行”原则。 -
数据库连接字符串必须外部化:通过环境变量(如
DB_URL)注入,而非硬编码在database.py中。Docker Compose 示例:services: bot: build: . environment: - DB_URL=postgresql://user:pass@postgres:5432/botdb app: build: ./app environment: - DB_URL=postgresql://user:pass@postgres:5432/botdb -
版本控制:
common/目录应纳入 Git,与项目同生命周期;若组件复用范围扩大,可进一步发布为私有 PyPI 包。 -
测试隔离:为
common/database编写单元测试时,使用pytest+pytest-mock模拟 psycopg2 连接,避免依赖真实数据库。
该方案在保持容器独立性的同时,实现了逻辑复用、部署一致性与长期可维护性——这才是云原生场景下 Python 服务间代码共享的正确姿势。











