Quickstart: Compose and Django

Overview of Docker Compose

Looking for Compose file reference? Find the latest version here.

Compose is a tool for defining and running multi-container Docker applications.

With Compose, you use a YAML file to configure your application’s services.

Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.

Compose works in all environments:

  • production,
  • staging,
  • development,
  • testing,
  • as well as CI workflows.

You can learn more about each case in Common Use Cases.

Using Compose is basically a three-step process:

  • Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
  • Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
  • Lastly, run docker-compose up and Compose will start and run your entire app.

Introduction

This quick-start guide demonstrates how to use Docker Compose to set up and run a simple Django/PostgreSQL app.

Before starting, you’ll need to have Compose installed.

Define the project components

For this project, you need to create a Dockerfile, a Python dependencies file, and a docker-compose.yml file. (You can use either a .yml or .yaml extension for this file.)

mkdir django_app

Create an empty project directory.

You can name the directory something easy for you to remember. This directory is the context for your application image. The directory should only contain resources to build that image.

mkdir django_app

Create a Dockerfile

Create a new file called Dockerfile in your project directory.

1
2
3
4
5
6
7
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

The Dockerfile defines an application’s image content via one or more build commands that configure that image.

Once built, you can run the image in a container.

For more information on Dockerfile, see the Docker user guide and the Dockerfile reference.

This Dockerfile starts with a Python 3 parent image.

Les images Python

Le tag python:3 correspond à la version courante en 2018 c’est à dire 3.6.

The parent image is modified by adding a new code directory. The parent image is further modified by installing the Python requirements defined in the requirements.txt file.

Create a requirements.txt in your project directory

This file is used by the RUN pip install -r requirements.txt command in your Dockerfile.

1
2
django
psycopg2

Create a file called docker-compose.yml in your project directory

The docker-compose.yml file describes the services that make your app.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
version: '3'

services:
  db:
    image: postgres
  web:
    build: .
    command: python3 manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

This file defines two services: The db service and the web service.

Les images postresql

../../_images/postgresql_tags.png

Les images PostgreSQL voir https://store.docker.com/images/postgres

The compose file also describes which Docker images these services use, how they link together, any volumes they might need mounted inside the containers.

See the docker-compose.yml reference for more information on how this file works

Create a Django project

In this step, you create a Django starter project by building the image from the build context defined in the previous procedure.

cd django_app

Change to the root of your project directory.

docker-compose run web django-admin.py startproject composeexample .

This instructs Compose to run django-admin.py startproject composeexample in a container, using the web service’s image and configuration.

Because the web image doesn’t exist yet, Compose builds it from the current directory, as specified by the build: . line in docker-compose.yml.

docker-compose run web django-admin.py startproject composeexample .
../../_images/docker_compose_startproject.png

docker-compose run web django-admin.py startproject composeexample .

Pulling db (postgres:latest)...
latest: Pulling from library/postgres
723254a2c089: Pull complete
39ec0e6c372c: Pull complete
ba1542fb91f3: Pull complete
c7195e642388: Pull complete
95424deca6a2: Pull complete
2d7d4b3a4ce2: Pull complete
fbde41d4a8cc: Pull complete
880120b92add: Pull complete
9a217c784089: Pull complete
d581543fe8e7: Pull complete
e5eff8940bb0: Pull complete
462d60a56b09: Pull complete
135fa6b9c139: Pull complete
Digest: sha256:3f4441460029e12905a5d447a3549ae2ac13323d045391b0cb0cf8b48ea17463
Status: Downloaded newer image for postgres:latest
Creating djangoapp_db_1 ... done
Building web
Step 1/7 : FROM python:3
3: Pulling from library/python
f49cf87b52c1: Already exists
7b491c575b06: Pull complete
b313b08bab3b: Pull complete
51d6678c3f0e: Pull complete
09f35bd58db2: Pull complete
0f9de702e222: Pull complete
73911d37fcde: Pull complete
99a87e214c92: Pull complete
Digest: sha256:98149ed5f37f48ea3fad26ae6c0042dd2b08228d58edc95ef0fce35f1b3d9e9f
Status: Downloaded newer image for python:3
 ---> c1e459c00dc3
Step 2/7 : ENV PYTHONUNBUFFERED 1
 ---> Running in 94847219310a
Removing intermediate container 94847219310a
 ---> 221d2e9ab9e4
Step 3/7 : RUN mkdir /code
 ---> Running in a65c8bf5e5a9
Removing intermediate container a65c8bf5e5a9
 ---> 589950689c7a
Step 4/7 : WORKDIR /code
Removing intermediate container f7b978400775
 ---> e039064473fb
Step 5/7 : ADD requirements.txt /code/
 ---> 4305caf141b9
Step 6/7 : RUN pip install -r requirements.txt
 ---> Running in 0705839561d0
Collecting django (from -r requirements.txt (line 1))
  Downloading Django-2.0.1-py3-none-any.whl (7.1MB)
Collecting psycopg2 (from -r requirements.txt (line 2))
  Downloading psycopg2-2.7.3.2-cp36-cp36m-manylinux1_x86_64.whl (2.7MB)
Collecting pytz (from django->-r requirements.txt (line 1))
  Downloading pytz-2017.3-py2.py3-none-any.whl (511kB)
Installing collected packages: pytz, django, psycopg2
Successfully installed django-2.0.1 psycopg2-2.7.3.2 pytz-2017.3
Removing intermediate container 0705839561d0
 ---> fa8182703037
Step 7/7 : ADD . /code/
 ---> 72d70c82ea04
Successfully built 72d70c82ea04
Successfully tagged djangoapp_web:latest
WARNING: Image for service web was built because it did not already exist.
To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.

Once the web service image is built, Compose runs it and executes the django-admin.py startproject command in the container. This command instructs Django to create a set of files and directories representing a Django project.

tree /a /f .

Y:\projects_id3\P5N001\XLOGCA135_tutorial_docker\tutorial_docker\compose\django\django_app>tree /a /f .
Y:\PROJECTS_ID3\P5N001\XLOGCA135_TUTORIAL_DOCKER\TUTORIAL_DOCKER\COMPOSE\DJANGO\DJANGO_APP
|   docker-compose.yml
|   Dockerfile
|   manage.py
|   requirements.txt
|
\---composeexample
                settings.py
                urls.py
                wsgi.py
                __init__.py

Connect the database

In this section, you set up the database connection for Django.

Edit the composeexample/settings.py file

In your project directory, edit the composeexample/settings.py file.

Replace the DATABASES = … with the following:

DATABASES = {
        'default': {
                'ENGINE': 'django.db.backends.postgresql',
                'NAME': 'postgres',
                'USER': 'postgres',
                'HOST': 'db',
                'PORT': 5432,
        }
}

These settings are determined by the postgres Docker image specified in docker-compose.yml.

django_app> docker-compose up

Run the docker-compose up command from the top level directory for your project.

Y:\projects_id3\P5N001\XLOGCA135_tutorial_docker\tutorial_docker\compose\django\django_app>docker-compose up
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

djangoapp_db_1 is up-to-date
Creating djangoapp_web_1 ... done
Attaching to djangoapp_db_1, djangoapp_web_1
db_1   | The files belonging to this database system will be owned by user "postgres".
db_1   | This user must also own the server process.
db_1   |
db_1   | The database cluster will be initialized with locale "en_US.utf8".
db_1   | The default database encoding has accordingly been set to "UTF8".
db_1   | The default text search configuration will be set to "english".
db_1   |
db_1   | Data page checksums are disabled.
db_1   |
db_1   | fixing permissions on existing directory /var/lib/postgresql/data ... ok
db_1   | creating subdirectories ... ok
db_1   | selecting default max_connections ... 100
db_1   | selecting default shared_buffers ... 128MB
db_1   | selecting dynamic shared memory implementation ... posix
db_1   | creating configuration files ... ok
db_1   | running bootstrap script ... ok
db_1   | performing post-bootstrap initialization ... ok
db_1   | syncing data to disk ... ok
db_1   |
db_1   | WARNING: enabling "trust" authentication for local connections
db_1   | You can change this by editing pg_hba.conf or using the option -A, or
db_1   | --auth-local and --auth-host, the next time you run initdb.
db_1   |
db_1   | Success. You can now start the database server using:
db_1   |
db_1   |     pg_ctl -D /var/lib/postgresql/data -l logfile start
db_1   |
db_1   | ****************************************************
db_1   | WARNING: No password has been set for the database.
db_1   |          This will allow anyone with access to the
db_1   |          Postgres port to access your database. In
db_1   |          Docker's default configuration, this is
db_1   |          effectively any other container on the same
db_1   |          system.
db_1   |
db_1   |          Use "-e POSTGRES_PASSWORD=password" to set
db_1   |          it in "docker run".
db_1   | ****************************************************
db_1   | waiting for server to start....2018-01-18 09:51:04.629 UTC [37] LOG:  listening on IPv4 address "127.0.0.1", port 5432
db_1   | 2018-01-18 09:51:04.630 UTC [37] LOG:  could not bind IPv6 address "::1": Cannot assign requested address
db_1   | 2018-01-18 09:51:04.630 UTC [37] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
db_1   | 2018-01-18 09:51:04.755 UTC [37] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1   | 2018-01-18 09:51:04.916 UTC [38] LOG:  database system was shut down at 2018-01-18 09:51:02 UTC
db_1   | 2018-01-18 09:51:04.976 UTC [37] LOG:  database system is ready to accept connections
db_1   |  done
db_1   | server started
db_1   | ALTER ROLE
db_1   |
db_1   |
db_1   | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
db_1   |
db_1   | 2018-01-18 09:51:05.165 UTC [37] LOG:  received fast shutdown request
db_1   | waiting for server to shut down....2018-01-18 09:51:05.224 UTC [37] LOG:  aborting any active transactions
db_1   | 2018-01-18 09:51:05.226 UTC [37] LOG:  worker process: logical replication launcher (PID 44) exited with exit code 1
db_1   | 2018-01-18 09:51:05.228 UTC [39] LOG:  shutting down
db_1   | 2018-01-18 09:51:05.860 UTC [37] LOG:  database system is shut down
db_1   |  done
db_1   | server stopped
db_1   |
db_1   | PostgreSQL init process complete; ready for start up.
db_1   |
db_1   | 2018-01-18 09:51:05.947 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db_1   | 2018-01-18 09:51:05.947 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db_1   | 2018-01-18 09:51:06.080 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1   | 2018-01-18 09:51:06.278 UTC [55] LOG:  database system was shut down at 2018-01-18 09:51:05 UTC
db_1   | 2018-01-18 09:51:06.340 UTC [1] LOG:  database system is ready to accept connections
web_1  | Performing system checks...
web_1  |
web_1  | System check identified no issues (0 silenced).
web_1  |
web_1  | You have 14 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
web_1  | Run 'python manage.py migrate' to apply them.
web_1  | January 18, 2018 - 10:46:37
web_1  | Django version 2.0.1, using settings 'composeexample.settings'
web_1  | Starting development server at http://0.0.0.0:8000/
web_1  | Quit the server with CONTROL-C.

At this point, your Django app should be running at port 8000 on your Docker host.

On Docker for Mac and Docker for Windows, go to http://localhost:8000 on a web browser to see the Django welcome page

docker ps

Y:\projects_id3\P5N001\XLOGCA135_tutorial_docker\tutorial_docker>docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
30b4922c00b2        djangoapp_web       "python3 manage.py r…"   About an hour ago   Up About an hour    0.0.0.0:8000->8000/tcp   djangoapp_web_1
0883a9ef1c3b        postgres            "docker-entrypoint.s…"   2 hours ago         Up 2 hours          5432/tcp                 djangoapp_db_1

django_app> docker-compose down

Y:\projects_id3\P5N001\XLOGCA135_tutorial_docker\tutorial_docker\compose\django\django_app>docker-compose down
Stopping djangoapp_web_1 ... done
Stopping djangoapp_db_1  ... done
Removing djangoapp_web_1     ... done
Removing djangoapp_web_run_1 ... done
Removing djangoapp_db_1      ... done
Removing network djangoapp_default