Skip to content

Commit 16d6f83

Browse files
committed
Create django-postgresql-docker.md
1 parent d6d5325 commit 16d6f83

1 file changed

Lines changed: 231 additions & 0 deletions

File tree

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# Django and PostgreSQL setup in Docker
2+
3+
Here is how to dockerize a Django app along side a PostgreSQL database container.
4+
5+
This guide shows how to integrate the following tools:
6+
7+
- Docker containers
8+
- uv package manager
9+
- Django app
10+
- PostgreSQL database
11+
12+
13+
## Setup project
14+
15+
Project folder structure:
16+
17+
```bash
18+
test-django-docker
19+
├── .venv
20+
├── my_django_app
21+
│ ├── my_django_app
22+
│ ├── core
23+
│ └── manage.py
24+
├── pyproject.toml
25+
├── readme.md
26+
├── requirements.txt
27+
└── uv.lock
28+
```
29+
30+
To set this up we create a root folder:
31+
32+
```bash
33+
mkdir test-django-docker
34+
cd test-django-docker
35+
```
36+
37+
Since we are using `uv` to manage packages and environments we initiate it:
38+
39+
```bash
40+
uv init .
41+
```
42+
43+
Now lets create the Django project `my_django_app` and create the app `core`.
44+
45+
```bash
46+
uv run django-admin startproject my_django_app
47+
cd my_django_app
48+
uv run python manage.py startapp core
49+
```
50+
51+
On the root folder create a `requirements.txt` file:
52+
53+
```bash
54+
cd ..
55+
uv pip freeze > requirements.txt
56+
```
57+
58+
59+
## Adding `gunicorn`
60+
61+
Django `manage.py runserver` is only meant for development purposes and should be changed for a WSGI server for production.
62+
63+
```bash
64+
uv add gunicorn
65+
uv add "psycopg[binary]"
66+
uv pip freeze > requirements.txt
67+
```
68+
69+
70+
## Create a Dockerfile
71+
72+
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:
73+
74+
```dockerfile
75+
# Use the official Python runtime image
76+
FROM python:3.11.13-slim-bookworm
77+
78+
# Create the app directory
79+
RUN mkdir /app
80+
81+
# Set the working directory inside the container
82+
WORKDIR /app
83+
84+
# Set several environment variables:
85+
# Prevents Python from writing pyc files to disk
86+
ENV PYTHONDONTWRITEBYTECODE=1
87+
88+
# Prevents Python from buffering stdout and stderr
89+
ENV PYTHONUNBUFFERED=1
90+
91+
# Upgrade pip
92+
RUN pip install --upgrade pip
93+
94+
# Copy the Django project and install dependencies
95+
COPY requirements.txt /app/
96+
97+
# Install all dependencies
98+
RUN pip install --no-cache-dir -r requirements.txt
99+
100+
# Copy the Django project to the container
101+
COPY . /app/
102+
103+
# Expose the Django port
104+
EXPOSE 8000
105+
106+
# Run Django development server
107+
# CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
108+
109+
# Start the application using Gunicorn
110+
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "my_django_app.wsgi:application"]
111+
```
112+
113+
Build the Docker container:
114+
115+
```bash
116+
docker build -t django-docker .
117+
```
118+
119+
To see your image, you can run:
120+
121+
```bash
122+
docker image list
123+
```
124+
125+
126+
## Configure the Docker Compose file
127+
128+
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.
129+
130+
```yaml
131+
services:
132+
web:
133+
build: .
134+
container_name: django_app
135+
ports:
136+
- "8000:8000"
137+
volumes:
138+
- ./my_django_app:/app
139+
depends_on:
140+
db:
141+
condition: service_healthy
142+
restart: true
143+
env_file:
144+
- .env
145+
db:
146+
image: postgres:17
147+
container_name: postgres_db
148+
environment:
149+
POSTGRES_DB: ${POSTGRES_DB}
150+
POSTGRES_USER: ${POSTGRES_USER}
151+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
152+
healthcheck:
153+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
154+
interval: 10s
155+
retries: 5
156+
start_period: 30s
157+
timeout: 10s
158+
ports:
159+
- "5432:5432"
160+
volumes:
161+
- postgres_db:/var/lib/postgresql/data
162+
env_file:
163+
- .env
164+
volumes:
165+
postgres_db:
166+
```
167+
168+
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.
169+
170+
```
171+
POSTGRES_DB=postgres_db
172+
POSTGRES_USER=dbuser
173+
POSTGRES_PASSWORD=dbpassword
174+
POSTGRES_HOST=db
175+
POSTGRES_PORT=5432
176+
```
177+
178+
179+
## Update Django settings and configuration files
180+
181+
Let's update the `setting.py` file by:
182+
183+
- Adding the `core` app.
184+
185+
- 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.
186+
187+
- Configure the database settings to use PostgreSQL.
188+
189+
```python
190+
import os
191+
192+
# ...
193+
194+
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY")
195+
196+
DEBUG = bool(os.environ.get("DEBUG", default=0))
197+
198+
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS","127.0.0.1").split(",")
199+
200+
# ...
201+
202+
INSTALLED_APPS = [
203+
# ...
204+
'core',
205+
]
206+
207+
# ...
208+
209+
DATABASES = {
210+
'default': {
211+
'ENGINE': 'django.db.backends.postgresql',
212+
'NAME': os.environ['POSTGRES_DB'],
213+
'USER': os.environ['POSTGRES_USER'],
214+
'PASSWORD': os.environ['POSTGRES_PASSWORD'],
215+
'HOST': os.environ['POSTGRES_HOST'],
216+
'PORT': os.environ['POSTGRES_PORT'],
217+
}
218+
}
219+
```
220+
221+
222+
223+
224+
225+
## References
226+
227+
- [Docker - Django and PostgreSQL setup (with uv) from scratch!](https://www.youtube.com/watch?v=37aNpE-9dD4)
228+
229+
- [How to Dockerize a Django App: Step-by-Step Guide for Beginners](https://www.docker.com/blog/how-to-dockerize-django-app/)
230+
231+
- [Dockerizing Django with Postgres, Gunicorn, and Nginx](https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/)

0 commit comments

Comments
 (0)