pythondjangodockerdocker-composepdm

How to set up docker compose with django and pdm


I have a django project with pdm and docker compose and I set up the codebase volume to enable django hot reload and debugging in the container. Building with the compose config works fine but when I try to run the server with docker compose up -d I hit a python error as if the libs were not picked up properly.

The project has the following architecture

project/
├── config/
│   ├── settings.py
│   └── urls.py
│   └── ...
├── some_django_app/
│   └── ...
├── compose.yaml
├── Dockerfile
├── README.md
├── pyproject.toml
└── pdm.lock

the compose file is as follows

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

my dockerfile is as follows

# 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;

Here is the trace of the error when I up the container

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?

It is as if pdm couldn't pick up my local libs. When I remove the container line in my compose file and rebuild, django runs fine. What is wrong with my configuration?


Solution

  • I ended up using a multistage approach as described with the PDM doc so PDM is used only during the build and not at runtime. To make sure the container .venv is not overwritten by the codebase venv, I also added a specific named container as follows:

    services:
      web:
        build:
          dockerfile: Dockerfile
        command: pdm run python manage.py runserver 0.0.0.0:8000
        ports:
          - 8000:8000
        volumes:
          - .:/app
          - venv:/app/.venv
        env_file:
          - .env
    
    volumes:
      venv:
    

    This solved my problem: I can still use pdm and docker during development and have a volume for the codebase.