Docker Compose配置Django+PDM时依赖无法加载的问题排查
问题
我有一个使用PDM管理依赖的Django项目,通过Docker Compose进行容器化部署。为实现Django热重载与容器内调试,配置了代码库卷挂载。镜像构建正常,但执行docker compose up -d启动容器时出现Python错误,仿佛依赖库未被正确识别。
项目架构
project/ ├── config/ │ ├── settings.py │ └── urls.py │ └── ... ├── some_django_app/ │ └── ... ├── compose.yaml ├── Dockerfile ├── README.md ├── pyproject.toml └── pdm.lock
compose.yaml 内容
services: web: build: dockerfile: Dockerfile command: pdm run python manage.py runserver 0.0.0.0:8000 ports: - 8000:8000 volumes: - .:/app env_file: - .env
Dockerfile 内容
# Use an official Python runtime as a parent image FROM python:3.13.2-slim-bullseye # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 # Set the working directory in the container WORKDIR /app # Install system dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpq-dev \ && rm -rf /var/lib/apt/lists/* # Install PDM RUN pip install --no-cache-dir pdm # Copy the project files into the container COPY . /app # Accept build argument for ENVIRONMENT ARG ENVIRONMENT=prod # Install project dependencies using PDM pdm install --prod --no-lock --no-editable;
容器启动错误栈
INFO: The saved Python interpreter does not exist or broken. Trying to find another one. INFO: __pypackages__ is detected, using the PEP 582 mode Traceback (most recent call last): File "/app/manage.py", line 12, in main from django.core.management import execute_from_command_line ModuleNotFoundError: No module named 'django' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/app/manage.py", line 23, in <module> main() ~~~~^^ File "/app/manage.py", line 14, in main raise ImportError( ...<3 lines>... ) from exc ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
移除compose文件中的卷配置并重建镜像后,Django可正常运行。请问我的配置哪里出现了问题?
解决方案
问题根源
- 挂载覆盖依赖目录:Dockerfile中执行
pdm install时,依赖会被安装到容器内的/app/__pypackages__目录(PEP 582模式)。但启动容器时,你用本地目录挂载覆盖了容器内的/app,导致容器内的依赖目录被本地目录替换——本地机器大概率没有这个目录,因此PDM找不到Django。 - Dockerfile语法错误:
pdm install命令缺少RUN前缀,属于构建阶段的语法问题(你提到镜像构建正常,可能是输入笔误,但必须修正)。
修复步骤
修正Dockerfile语法
给pdm install命令加上RUN前缀,确保构建阶段正确执行依赖安装:# Install project dependencies using PDM RUN pdm install --prod --no-lock --no-editable避免挂载覆盖依赖目录
不要直接挂载整个/app,而是选择性挂载需要热重载的代码目录,保留容器内的依赖目录:volumes: # 挂载核心代码目录,保留容器内的__pypackages__ - ./config:/app/config - ./some_django_app:/app/some_django_app - ./manage.py:/app/manage.py # 若需要同步依赖配置,可单独挂载pyproject.toml - ./pyproject.toml:/app/pyproject.toml或者使用Docker Compose的挂载排除规则(3.2+版本支持),直接排除依赖目录:
volumes: - .:/app - /app/__pypackages__ - /app/.pdm.toml第二条规则表示保留容器内的
__pypackages__目录,不被本地挂载覆盖。可选:切换PDM运行模式
如果你偏好虚拟环境而非PEP 582,可在Dockerfile中添加环境变量:ENV PDM_VENV_IN_PROJECT=1然后修改依赖安装命令:
RUN pdm install --prod --no-lock此时依赖会安装到容器内的
.venv目录,挂载时同样排除该目录即可。
验证
修改后重新构建镜像并启动容器:
docker compose build docker compose up -d
此时代码修改会同步到容器,依赖目录不受挂载影响,Django可正常加载。
内容的提问来源于stack exchange,提问作者Martin Faucheux
相关产品推荐
相关产品推荐

