You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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可正常运行。请问我的配置哪里出现了问题?


解决方案

问题根源

  1. 挂载覆盖依赖目录:Dockerfile中执行pdm install时,依赖会被安装到容器内的/app/__pypackages__目录(PEP 582模式)。但启动容器时,你用本地目录挂载覆盖了容器内的/app,导致容器内的依赖目录被本地目录替换——本地机器大概率没有这个目录,因此PDM找不到Django。
  2. Dockerfile语法错误:pdm install命令缺少RUN前缀,属于构建阶段的语法问题(你提到镜像构建正常,可能是输入笔误,但必须修正)。

修复步骤

  1. 修正Dockerfile语法
    给pdm install命令加上RUN前缀,确保构建阶段正确执行依赖安装:

    # Install project dependencies using PDM
    RUN pdm install --prod --no-lock --no-editable
    
  2. 避免挂载覆盖依赖目录
    不要直接挂载整个/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__目录,不被本地挂载覆盖。

  3. 可选:切换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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:06:12