如何让多个Docker应用共享本地Python代码库并支持热重载?
问题描述
我希望在多个Docker镜像/容器应用中,将共享Python代码库作为本地依赖使用。
目录结构如下:
my-projects/ |-projectlib/ | |-__init__.py | |-utils.py | |-my-app-1/ | |-app.py | |-Dockerfile | |-docker-compose.yaml | |-my-app-2/ |-app.py |-Dockerfile |-docker-compose.yaml
我希望两个app.py在Docker镜像中都能访问projectlib。即在my-app-1目录下执行docker compose build时,构建上下文等效于:
|-my-app-1/ |-app.py |-Dockerfile |-docker-compose.yaml |projectlib/ |-__init__.py |-utils.py
因为在app.py中有如下导入语句:
from projectlib.utils import connect_to_db
需求原因
- 我每天会多次修改
projectlib,不希望在每个my-app-*目录中保留副本,避免版本不一致。 - 理想状态下,
projectlib/目录能被挂载到容器中,这样当我修改utils.py时,正在运行的app.py(Streamlit和FastAPI应用)能实现热重载。
注:以上均针对开发流程,部署流程是独立的,我清楚修改
utils.py时可能导致所有应用崩溃的风险。
备选方案
- 通过bash脚本将
projectlib/复制到构建上下文,再执行docker compose build
是否有更优的实现方式?
最优实现方案
针对开发场景,推荐两种更高效的方式,兼顾构建时的依赖引入和运行时的热重载需求:
方式一:调整构建上下文+Dockerfile复制
操作步骤:
- 修改
my-app-1的docker-compose.yaml:
将构建上下文指向父目录,让Docker能访问到projectlib:services: app: build: context: ../ # 指向my-projects根目录 dockerfile: my-app-1/Dockerfile # 指定当前应用的Dockerfile路径 - 更新
my-app-1的Dockerfile:
直接从父上下文复制共享库和应用代码:FROM python:3.11-slim WORKDIR /app # 复制共享库和当前应用代码 COPY projectlib/ ./projectlib/ COPY my-app-1/ . # 安装应用依赖 RUN pip install --no-cache-dir -r requirements.txt CMD ["python", "app.py"] - 执行构建命令:
依然在my-app-1目录下运行:docker compose build
优势:
- 无需手动复制文件,直接利用父目录作为构建上下文,从根源避免版本不一致
- 构建后的镜像包含完整依赖,可直接用于本地测试
方式二:开发时挂载目录+构建时本地安装(推荐)
这种方式完美适配开发阶段的热重载需求,同时遵循Python包管理规范:
操作步骤:
- 为
projectlib添加包配置文件:
在projectlib目录下创建setup.py,将共享库包装成可安装的Python包:from setuptools import setup, find_packages setup( name="projectlib", version="0.1.0", packages=find_packages(), ) - 修改
my-app-1的requirements.txt:
添加本地依赖指向:../projectlib/ - 在
docker-compose.yaml配置开发挂载:
运行时将本地projectlib挂载到容器的Python包路径,实现热重载:services: app: build: . volumes: - ../projectlib:/usr/local/lib/python3.11/site-packages/projectlib # 挂载共享库到容器包目录 - .:/app # 挂载当前应用代码(若需热重载app.py) # FastAPI热重载命令示例 command: ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] # Streamlit热重载命令示例 # command: ["streamlit", "run", "app.py", "--server.port", "8501"] - 简化
Dockerfile:FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"]
优势:
- 开发时修改
projectlib代码会实时同步到容器,立即触发应用热重载 - 构建镜像时自动安装最新版本的
projectlib,无需手动复制文件 - 符合Python包管理规范,后续可轻松将
projectlib发布到私有仓库用于部署
注意事项:
- 以上两种方式均仅适用于开发环境,部署时建议将
projectlib打包为固定版本的wheel文件,再添加到镜像中,避免依赖变动影响生产环境 - 使用方式二时,需确保容器内Python版本与本地一致,否则挂载的包可能无法正常运行
内容的提问来源于stack exchange,提问作者MYK
相关产品推荐
相关产品推荐

