Quick introduction to Docker containers for Django developer
- Transfer

The development of such a project as a cashback service involves the use of various services that are not typical for a regular laptop, even if it is a developer's laptop. Postgresql, Redis, Celery and so on. The desire to create a comfortable development and testing environment led us to the need to use some kind of virtualization / isolation system. Alternatively, Vagrant has been used for some time, but it's still ovrerhead and our search for the best way has led, at the moment, to Docker.
Docker- A platform for launching applications in isolated containers. Using containers on Linux allows software to be isolated from the underlying system. Unlike Virtualbox, the system overhead required for equipment virtualization is excluded. Docker can help develop and deploy web applications and services. Let's see how this happens.
Why do I need a docker?
Docker can be used in a variety of ways. It can provide services in the background, for example, PostgreSQL with a given version. Our dockerizing application can be placed in docker, and so we can use images of similar containers to deploy our application on production.
For python developers, Docker can be described as virtualenv for any application. It can be either a Python interpreter or some server. This is very convenient when you want to test new versions or want to run outdated applications on your server.
Install Docker
Docker is available in repositories on various Linux distributions. OSX and MS Windows users can use VirtualBox, on which the Linux system is installed in order to run Docker.
To install the latest version, I use PPA for Ubuntu. When Docker is installed, you can add yourself to the docker group so that you do not need to use sudo in the future.
First containers
When Docker is ready, we can launch many containers from registry.hub.docker.com , for example Python. To run this container, simply do:
docker run -it --rm python:3.4
To start, running Docker will download several files. When the process is completed, we will get the default console of the Python interpreter. The -it command launches the container interactively and binds it to the console for interaction. --rm will delete the current container after exiting. “Python” is the name of the source for the container. After “:” we see a tag that usually shows the version - in this case, the version of Python in the container.
We can also change the standard behavior of the container, for example, run our own script. To use a command from the command line, simply add the following:
docker run -it --rm python:3.4 ls
When our container is launched, the “ls” command will be launched inside it, which will show all the files and filters in the main directory.
Dockerfile
The Dockerfile contains the “recipe” for our container. If we want to run a script in Python, here is what we have to write:
FROM python:3.4
ADD ./test.py /
RUN ls -al
CMD python test.py
FROM points to the base container, in this case, the Python 3.4 image. Further we can use ADD , RUN, ENV commands to configure the container. The RUN team will perform tasks when the container is built. The CMD command will execute at the start of the container launch. Image building operations are cached and skips the following versions (the RUN command from the example will start building the first build, but not the second).
In the terminal, we can write the following:
docker build --tag=foo .
docker run -it --rm foo
Django Dockerfile
django-ckeditor contains a demo application that can be launched via manage.py and runserver. Let's try to make a Dockfile that will create an image of this application:
FROM python:3.4
MAINTAINER Piotr Maliński <riklaunim@gmail.com>
ADD . /ckeditor
ENV DJANGO_SETTINGS_MODULE ckeditor_demo.settings
RUN pip install -r /ckeditor/ckeditor_demo_requirements.txt
RUN pip install /ckeditor
RUN python /ckeditor/manage.py validate
RUN python /ckeditor/manage.py collectstatic --noinput
CMD python /ckeditor/manage.py runserver 0.0.0.0:8080
I am using Python 3.4 here. All code from the repository will be added to the “ckeditor” folder of the container. I also set the DJANGO_SETTINGS_MODULE environment variable, add dependencies and the editor itself. Further validation, collection of statics and at the end of CMD to start the server. It is also convenient to make the server accessible outside the container, for this we run it on 0.0.0.0 IP
dockebuild --tag=django-ckeditor .
dockerun -it --rm --publish=192.168.0.110:8080:8080 django-ckeditor
The --publish option allows mapping public IP / Port addresses from a running local container to a local one. In this example, 192.168.0.110 is the host port. The public port can be accessed through 8080 from my localhost. Without the publish option, the server will be accessible only from the running IP address of the container.
The Dockerfile configuration that I showed is not perfect and will only work with SQLite database. Docker allows you to run different services in different containers. For example, let's try using a PostgreSQL database in a second container.
So let's run the PostgreSQL instance:
docker run -d postgres:9.4
The container will start in the background and we can check its status and name with the docker ps command . The default names are random, for example, “clever_ptolemy”. Now we have created a database on this server, but first we need an IP address. We can get it from docker inspect INSTANCE_NAME , which will show a list of variables in the container, including the IP address. Further we can create a database:
createdb -h IP_ADDRESS DATABASE_NAME -U postgres
The database has been created and now we can configure it in the application container. Docker allows you to do this using environment variables. For Django, you can use dj_database_url :
from os import environ
import dj_database_url
DATABASES = {'default': dj_database_url.parse(environ.get('DATABASE', 'postgres:///'))}
Now we need to pass env a variable with the database name to the container to make it work. It could be done like this:
docker run -it --rm --link=POSTGRES_INSTANCE_NAME:OUR_NAME -e DATABASE=postgres://postgres@OUR_NAME/DATABASE_NAME --publish=192.168.0.110:8080:8080 django-ckeditor
We can get the name of the database instance by executing the “docker ps” command in the console. “OUR_NAME” is a shortcut that we can use later in the -e value. In my case, it looked like this:
docker run -it --rm --link=clever_ptolemy:db -e DATABASE=postgres://postgres@db/ckeditor --publish=192.168.0.110:8080:8080 django-ckeditor python /ckeditor/manage.py syncdb
docker run -it --rm --link=clever_ptolemy:db -e DATABASE=postgres://postgres@db/ckeditor --publish=192.168.0.110:8080:8080 django-ckeditor
The syncdb command is executed first, it will create tables in the database. Next, the development server starts.
Fig tool
The simple example described above requires many names and links. In order to make the process easier, there are several tools like fig. In the YAML (fig.yml) file we can specify all the steps and links that are needed:
ckeditor:
build: .
command: python /ckeditor/manage.py runserver 0.0.0.0:8080
links:
- db
ports:
- "8080:8080"
db:
image: postgres:9.4
Next, we can build with the fig build command and run c fig up , which will show the application. We have several labels and we can run syncdb and use fig run NAME COMMAND to help , where Name is the instance name fig.yml. When fig starts up, you can check the list of containers with the “docker ps” command.
You can read more about fig.yml syntax on the application page. There is also a Django tutorial that provides another way to configure Postgres.