Docker Compose for Django development by Simon Willison ¶
Introduction ¶
I had to get Docker Compose working for a Django project, primarily to make it easier for other developers to get a working development environment.
Some features of this project ¶
-
Uses GeoDjango, so needs GDAL etc for the Django app plus a PostgreSQL server running PostGIS
-
Already has a Dockerfile used for the production deployment, but needed a separate one for the development environment
-
Makes extensive use of Django migrations (over 100 and counting)
I ended up with this docker-compose.yml file in the root of the project:
1 version: "3.1"
2
3 services:
4 database:
5 image: postgis/postgis:13-3.1
6 restart: always
7 expose:
8 - "5432"
9 ports:
10 - "5432:5432"
11 environment:
12 POSTGRES_USER: postgres
13 POSTGRES_DB: mydb
14 POSTGRES_PASSWORD: postgres
15 web:
16 container_name: myapp
17 build:
18 context: .
19 dockerfile: Dockerfile.dev
20 command: python manage.py runserver 0.0.0.0:3000
21 environment:
22 DATABASE_URL: postgres://postgres:postgres@database:5432/mydb
23 DEBUG: 1
24 volumes:
25 - .:/app
26 ports:
27 - "3000:3000"
28 depends_on:
29 - migrations
30 - database
31 migrations:
32 build:
33 context: .
34 dockerfile: Dockerfile.dev
35 command: python manage.py migrate --noinput
36 environment:
37 DATABASE_URL: postgres://postgres:postgres@database:5432/mydb
38 volumes:
39 - .:/app
40 depends_on:
41 - database
The db container runs PostGIS.
The web container runs the Django development server, built using the custom Dockerfile.dev Dockerfile.
The migrations container simply runs the apps migrations and then terminates - with depends_on used to ensure that migrations run after the hdatabase server starts and before the web server.
The container_name: myapp field on the web container is a convenience which means you can later run commands like this:
docker exec -it myapp ./manage.py collectstatic
Here’s Dockerfile.dev:
1 FROM python:3.9-slim
2
3 ENV APP_HOME /app
4 WORKDIR $APP_HOME
5
6 ENV PYTHONUNBUFFERED 1
7
8 # gdal for GeoDjango
9 RUN apt-get update && apt-get install -y \
10 binutils \
11 gdal-bin \
12 libproj-dev \
13 git \
14 && rm -rf /var/lib/apt/lists/*
15
16 COPY requirements.txt .
17 RUN pip install --no-cache-dir -r requirements.txt
18
19 WORKDIR $APP_HOME/myapp
20
21 RUN ./manage.py collectstatic --no-input