Django with Docker and Docker Compose (Python part 1)

Tariqul Islam
Analytics Vidhya
Published in
10 min readDec 5, 2019

I was inspired to write this post based on my experience trying to change my development environment with docker with django applications. I will try to write series of articles where will I give you concepts of

  1. Full stack development with docker and django application
  2. Test Driven Development with Django
  3. CI/CD pipline with automated deployment Digital Ocean and AWS.

Hopefully this article will help anyone out there who is feeling nervous with development using docker with any application.

What is docker?

Docker is an open-source tool that automates helps us to automated, package an application together inside a container which has all the information and dependency to run the application.It is more flexible, more portable, more resource-friendly, and more independent with host operating system.

What is django framework?

According to django documentation definition,

“Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.”

Prerequisites for building development environment

1. python > 3.7
2. pip3
3. pipenv
4. django 2.2
5. Docker installed in (window or linux or mac os x)

To install pipenv to development environment we need to follow below command.

For Mac OS x or Linux use this below command installed with python v3.7. if the Mac OS x or Linux already has a python version 2. You must use pip3 and python version 3 for django v2.2.> pip3 install pipenvFor window use this command installed with python v3.7. If you have version 2 installed in window pc. please use pip3 as default package manager.> pip install pipenv

Create the folder name django-docker and go to that folder by . Then go to that folder or directory

> mkdir django-docker
> cd django-docker

Create Another folder named app in django-docker directory . Then go to that directory

> mkdir app
> cd app

Then Install the Django (2.2.8) with pipenv , using pipenv:

> pipenv --python 3.7 install django==2.2.8

— python 3.7 means, specify the python version during create the virtual environment with pipenv.

Then to activate virtual environment, you needs to run the below command on terminal

> pipenv shell

Django Already installed as package, which you can find defination in Pipfile . To create the django project structure you need to use django-admin , and run below command to create project

> django-admin startproject main .

After that, you can open the django-docker directory at you favorite code editor or IDE, I am using vscode as default code editor for this article. you can use your suitable one.

Create the text file requirements.txt to app folder, Add the Django==2.2.8 to text file. I use that file building time from requirments.txt build the docker image and container with django.

requirments.txt file is like below:

#./django-docker/app/requirments.txt
#Packages
Django==2.2.8

Project Structure for django-docker

└── app
├── main
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── requirements.txt
└── Pipfile
└── Pipfile.lock

Every generated file is its own responsibility to run the django project

1. __init__.py (It tells the python, main is python module for this project and it's an empty file. so `main` will be access as python module)2. setting.py (It contains all the configuration related to django project)3. urls.py (It contains all the definition route information of every page of django application. it using for declare the url and route for each page of web application built with django)4. wsgi.py (This file is use for run the application uwsgi supported server. we can use this file to configure gunicorn web server)5. manage.py (It's an wizard for django application, to create app, module and views and manage migration, we will use this file)6. Pipfile ( It's is a difination file where pip takes the meta information to download package and build, setup the python package(Django Application)

To run the project, go to terminal or cmd to run this below command

> python manage.py runserver --insecure 0.0.0.0:5555
Figure 1.1 application run command

runserver command will run the django development server.

— insecure argument enable the django apps to run in local development environment. And force serving of static files with the staticfiles app.

0.0.0.0:<port>, we can define which port the django development server will serve the django web application.

we can see the warning in figure 1.1 in point (1), that warning related to database migration. We got that warning, because we do not migrate the database before run the application. django by default comes with sqlite database, if we run the migrate command it will migrate all it’s data and information to sqlite database. We do not need the migration at now in this part of this article.

So we can….Navigate to browser and http://localhost:4000 in browser you will see the django welcome page. So django is successfully installed in pipenv or virtual environment.

Figure 1.2 django application run successfully

Run the Django project in docker

Create Dockerfile docker file

First we need to go to root folder or directory of th project create filename Dockerfile . Now You have question about what is docker file.

Docker will build the image automatically by reading the instruction from Dockerfile. It is text file document which contains all the commands to assemble as image. it contains necessary package, applications, command and various settings to create the docker image. To dockerized the any application we need to have dockerfile in it.

From --> For build the docker image, From instraction must needed, because it will take the information from base image (OS base, other software package images) where to start building docker image.WORKDIR --> It is used for switch to that directory for copy or add files or run some command in that directory in container. It also helps to create the new directory, which are used for building the image, copy the code and settings to it.ENV --> It's use for environment variable of docker images. Docker image contains the lightweight operating system. we can push and override the environment variable from  calling it COPY --> Helps to copy the file from host machine to docker container.ADD --> Helps to copy the file from host machine to docker image or container. It as like as copy instractions, it has extra functionality, it copy the file from remote alsoRUN --> Run the command inside the docker image at image building time. It support valid operating system command.   executes command(s) in a new layer and creates a new imageCMD -->  sets default command and/or parameters, which can be overwritten from command line when docker container runsENTRYPOINT -->  used for configure the container that will run as an executable. We can add the multiple command shell file .sh file in entrypoint instructions. it will run EXPOSE --> It will help to expose the port for to in docker to access by other container or images. we also mapping with host computer port during run the docker container.

Here is the format of the Dockerfile:

# Comment
INSTRUCTION arguments

For django-docker application, I add the Dockerfile to app directory:

django-docker
└── app
├── main
│ ├── ......
├── Dockerfile

Dockerfile instruction are provide below for django-docker project. For development purpose i use python:3.7.5-buster as base image for build the docker image and container.

# ./django-docker/app/Dockerfile
FROM python:3.7.5-buster
# set work directory
WORKDIR /opt/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt /opt/app/requirements.txt
RUN chmod +x /opt/app/requirements.txt
RUN pip install -r requirements.txt
# copy project
COPY . /opt/app/

PYTHONDONTWRITEBYTECODE: Prevents Python from writing pyc files to disc. PYTHONUNBUFFERED: Prevents Python from buffering stdout and stderr.

Adding Docker Compose To Project

Then Add the docker compose file nameddocker-compose.yml at django-docker directory. Now you have question about what is docker compose and why it’s needed. As per docker compose documentation in docs.docker.com.

“Compose is a tool for defining and running multi-container Docker Applications or Services. Developer can use a YAML file to configure application services with a single command , it can create and start all service to get information from yml file.”

django-docker
└── app
│ ├── main
│ ├── ......
├── docker-compose.yml

I create the docker compose yml file, which instruction definition is provide below to create services and container for this web application project.

#./django-docker/docker-compose.yml
version
: '3.7'

services:
web:
build:
context: ./app
dockerfile: Dockerfile
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./app/:/opt/app/
ports:
- 4000:8000
env_file:
- ./env/django.env

Simple description of all keywords of docker-compose file,which are discuss below, if you already knows about the keywords or Instructions, please escape the section.

version: contains docker compose file format version. There is several file format available form 1.x to 3.x.services: services blocks contains all the applications or services definition which is needed for run the applications successfully. for example if we want to run the web apps, we need a database and other services. so we can add multiple service or app definitions in services blocks.web: web is service for our django-docker project, docker compose build images or services with using name as `web` by docker-compose, which contains definition of django application to run and deploy.

services:
web:
build:
build: there is a lot of option for build instruction. we can build image from another image. we can provide the target folder to build in `build` block. build has some sub blocks, those are

context: which will takes to a directory, which contains a Dockerfile, or a url to a git repository. where the value supplied with relative path, it will send to docker deamon to building process.
build:
context: ./<dir-name>
dockerfile: if we want to specify or use different docker file to build docker image by docker compose file. we need to use it.

build:
context: ./<dir-name>
dockerfile: <docker-filename>
command: Run the command in docker container from the docker-compose.yml file. it can run any valid os and os application command inside the container.volumes: we can mount the specific host path or named volume to docker contains which contains the media files and other files needed for run the application. for my apps i have to mount the /app folder to container.expose: provide port access to docker system so other container can access the service by this port. expose only publish the port within docker system, so host computer service or app can not get this port to access service.ports: it use for mapping the ports between HOST:DOCKERCONTAINER. other docker container service and host computer service can get access to that port, to get service information. if we run the our django application in 8000 port in DOCKERCONTAINER, we want to map 4000 port with host computer just follow the rules
ports:
- HOST-PORT:DOCKERCONTAINER-PORT
(e.g)
ports:
- 4000:8000
environment: it will add and override the environment variable to docker container or image. which is then you can use it as environment variable to the specified docker container image.env_file: we can add environment variable file there. we can use it also define the or override the environment variable of the docker container or image. we can add the multiple env file in env_file block.

Create env files for docker in env directory. first create the env directory in django-docker directory.Then create the file name django.env in env directory or folder

> mkdir env
> cd env
For Linux and max os x command
> touch django.env
For window you can create from IDE or code editor

The env file location will be shows below:

django-docker
└── app
│ ├── main
├── env
│ ├── django.env

Environment file for django-docker image and container

# ./django-docker/env/django.envSECRET_KEY=FirstProjectSecrit 
DEBUG=1
ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

Then you need to find some line and replace with below code settings.py in main project folder.

#./app/main/setting.pySECRET_KEY = os.environ.get("SECRET_KEY", default="forlocaltest")DEBUG = int(os.environ.get("DEBUG", default=1))ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS').split(" ") if os.environ.get('ALLOWED_HOSTS') else ['localhost', '127.0.0.1']

SECRET_KEY = Using by django application for security purpose. This is used to provide cryptographic signing, and should be set to a unique, unpredictable value. Running Django with a known SECRET_KEY defeats many of Django’s security protections, and can lead to privilege escalation and remote code execution vulnerabilities.

DEBUG = Run the application in debug mode, so developer can access the error when browsing from browser. Never deploy a site into production with DEBUG turned on. It Rise all the exception when Debug is True and Django will display a detailed traceback, including a lot of metadata about your environment, such as all the currently defined Django setting.

ALLOWED_HOSTS = A list of strings representing the host/domain names that this Django site can serve.

What does os.environ do?

os.environ is python utility library with mapping,and setting object with user’s environment variable of a operating system. in above, i create the env file, so when application run in docker container, that env files env variable are added to docker container OS. so we can get the evn environment variable data by using os.environ library using os.environ.get(‘env-variable’) function.

Command for Build the docker image with docker compose, it will build the image and up all the docker container service with specific port:

> docker-compose up --build

Or

You can run below command also it will build all the service or docker image and up the service and run the service in background (-d command argument provide the instruction to docker run the service in background) so we don’t see the command or log information in terminal.

> docker-compose up --build -d

Go to browser and navigate to http://localhost:4000/ to again view the welcome screen.

The full code and resource you found in github repository

--

--

Tariqul Islam
Analytics Vidhya

Tariqul Islam have 9+ years of software development experience. He knows Python, Node Js and Java, C# , PHP.