多容器部署Telegram Bot与小程序的架构设计及代码复用疑问
作为踩过类似坑的开发者,我来给你唠唠这俩问题的实际解法:
一、要不要把Bot和WebApp分成两个容器?
必须推荐分开! 不是说小项目不能凑一块跑,但从长远维护和扩展性来看,分开是绝对更明智的选择:
- 互不干扰:Bot要重启更新、或者因为消息量暴涨出问题时,完全不会影响WebApp的正常服务;反过来WebApp迭代升级也不用动Bot的容器,各自的生命周期彻底独立。
- 资源按需分配:Telegram Bot大概率要频繁处理消息队列,CPU波动可能会大;WebApp要处理用户的HTTP请求,内存需求可能更高。分开容器后能给各自单独设置资源限制,避免互相抢资源拖垮对方。
- 维护更省心:后续给其中一个服务加依赖、改配置,直接动对应容器的Dockerfile就行,不会污染另一个服务的运行环境。
当然如果你的项目现在还极小,代码加起来没几百行、访问量也低,先放一个容器里凑活跑也没问题,但建议尽早改成多容器架构,符合Docker“一个容器一个核心服务”的最佳实践。
二、怎么在两个容器里复用同一个database.py?
这是Docker里非常常见的代码复用场景,给你几个接地气的方案:
1. 做个共用基础镜像(生产环境首选)
把database.py和两个服务都需要的数据库依赖(比如psycopg2-binary、python-dotenv这类)打包成一个基础镜像,然后Bot和WebApp的镜像都基于这个基础镜像构建,不用重复做安装依赖、复制代码的操作。
举个实际的例子:
- 先写一个
Dockerfile.base:
FROM python:3.11-slim # 安装两个服务都要用的依赖 RUN pip install psycopg2-binary python-dotenv # 把共用的数据库操作代码复制进去 COPY database.py /app/database.py WORKDIR /app
- 然后Bot的
Dockerfile就可以这么写:
FROM my-common-base:latest # 只需要复制Bot专属的代码 COPY bot/ /app/bot/ CMD ["python", "/app/bot/main.py"]
- WebApp的
Dockerfile同理:
FROM my-common-base:latest # 复制WebApp专属代码 COPY webapp/ /app/webapp/ CMD ["python", "/app/webapp/main.py"]
构建的时候先打基础镜像:docker build -f Dockerfile.base -t my-common-base .,再分别构建Bot和WebApp的镜像就好。
2. 共用代码目录直接复制/挂载(中小项目&开发环境适用)
如果不想搞基础镜像这么麻烦,也可以把database.py放到一个单独的common目录里,然后在两个服务的Dockerfile里直接复制这个目录:
# Bot的Dockerfile示例 FROM python:3.11-slim # 安装Bot需要的所有依赖(包括共用的数据库依赖) RUN pip install psycopg2-binary python-dotenv python-telegram-bot # 复制共用代码和Bot专属代码 COPY common/ /app/common/ COPY bot/ /app/bot/ CMD ["python", "/app/bot/main.py"]
WebApp的Dockerfile照葫芦画瓢就行,然后在代码里用from common.database import *来引用共用的数据库操作逻辑。
开发阶段还能用Docker Compose的卷挂载功能,把本地的common目录挂到两个容器里,这样改了database.py不用重新构建镜像,直接生效,调试起来特别爽:
# docker-compose.yml示例 version: '3.8' services: bot: build: ./bot volumes: - ./common:/app/common webapp: build: ./webapp volumes: - ./common:/app/common postgres: image: postgres:15 environment: POSTGRES_USER: my_db_user POSTGRES_PASSWORD: my_db_pass POSTGRES_DB: my_bot_db
3. 把共用代码做成Python包(进阶玩法)
如果后续共用代码越来越多,比如除了database.py还要加工具函数、配置类之类的,可以把common目录做成一个可安装的Python包(加个pyproject.toml或者setup.py),然后在Bot和WebApp的requirements.txt里用相对路径引用,比如-e ./common,这样构建镜像时会自动安装这个本地包,代码里直接import就完事了。
最后碎碎念
刚开始用Docker不用追求完美,先用Docker Compose把Bot、WebApp、Postgres这三个服务跑起来,慢慢调整架构。比如先从“复制共用目录”的方式复用代码,等你对Docker熟悉了再过渡到基础镜像的方案,学习曲线会平缓很多。
备注:内容来源于stack exchange,提问作者Pixol20

