Django and PostgreSQL setup in Docker
Here is how to dockerize a Django app along side a PostgreSQL database container.
This guide shows how to integrate the following tools:
- Docker containers
- uv package manager
- Django app
- PostgreSQL database
Setup project
Project folder structure:
test-django-docker
├── .venv
├── my_django_app
│ ├── my_django_app
│ ├── core
│ └── manage.py
├── pyproject.toml
├── readme.md
├── requirements.txt
└── uv.lock
To set this up we create a root folder:
Since we are using uv to manage packages and environments we initiate it:
Now lets create the Django project my_django_app and create the app core.
uv run django-admin startproject my_django_app
cd my_django_app
uv run python manage.py startapp core
On the root folder create a requirements.txt file:
Adding gunicorn
Django manage.py runserver is only meant for development purposes and should be changed for a WSGI server for production.
Create a Dockerfile
A Dockerfile is a script that tells Docker how to build your Docker image. Put it in the root directory of your Django project. Here’s a basic Dockerfile setup for Django:
# Use the official Python runtime image
FROM python:3.11.13-slim-bookworm
# Create the app directory
RUN mkdir /app
# Set the working directory inside the container
WORKDIR /app
# Set several environment variables:
# Prevents Python from writing pyc files to disk
ENV PYTHONDONTWRITEBYTECODE=1
# Prevents Python from buffering stdout and stderr
ENV PYTHONUNBUFFERED=1
# Upgrade pip
RUN pip install --upgrade pip
# Copy the Django project and install dependencies
COPY requirements.txt /app/
# Install all dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the Django project to the container
COPY . /app/
# Expose the Django port
EXPOSE 8000
# Run Django development server
# CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
# Start the application using Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "my_django_app.wsgi:application"]
Build the Docker container:
To see your image, you can run:
Configure the Docker Compose file
A docker-compose.yml file allows you to manage multi-container applications. Here, we'll define both a Django container and a PostgreSQL database container.
services:
web:
build: .
container_name: django_app
ports:
- "8000:8000"
volumes:
- ./my_django_app:/app
depends_on:
db:
condition: service_healthy
restart: true
env_file:
- .env
db:
image: postgres:17
container_name: postgres_db
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
retries: 5
start_period: 30s
timeout: 10s
ports:
- "5432:5432"
volumes:
- postgres_db:/var/lib/postgresql/data
env_file:
- .env
volumes:
postgres_db:
The compose file makes use of an environment file called .env, which will make it easy to keep the settings separate from the application code.
POSTGRES_DB=postgres_db
POSTGRES_USER=dbuser
POSTGRES_PASSWORD=dbpassword
POSTGRES_HOST=db
POSTGRES_PORT=5432
Update Django settings and configuration files
Let's update the setting.py file by:
-
Adding the
coreapp. -
Change some variables to enable them to be set using environment variables when the container is started. This allows you to change these settings depending on the environment you are working in.
-
Configure the database settings to use PostgreSQL.
import os
# ...
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY")
DEBUG = bool(os.environ.get("DEBUG", default=0))
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS","127.0.0.1").split(",")
# ...
INSTALLED_APPS = [
# ...
'core',
]
# ...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['POSTGRES_DB'],
'USER': os.environ['POSTGRES_USER'],
'PASSWORD': os.environ['POSTGRES_PASSWORD'],
'HOST': os.environ['POSTGRES_HOST'],
'PORT': os.environ['POSTGRES_PORT'],
}
}
Finally, we can run the docker-compose.yaml file:
Executing commands
After something like creating models, you may want to run migrations:
docker exec django_app python manage.py makemigrations
docker exec django_app python manage.py migrate
And to access the PostgreSQL shell:
or to access the Django shell:
Creating an entrypoint
You may want to create an entrypoint.
In the same level as the manage.py file create a entrypoint.sh file:
#!/bin/sh
echo "Running migrations..."
python manage.py migrate
echo "Starting server..."
python manage.py runserver 0.0.0.0:8000
Then:
You can now go to your Dockerfile and change the final line: