Django — Development to Production with Docker
By: Oussama Amor
Tags: Deployment, Django, Docker

Let’s code!

We’ve been talking so long about the architecture and minor theoretical staff, let’s jump now to how to make this architecture alive.

To begin with, all of Supervisord, Nginx and Gunicon need a config file, which is responsible of giving the instruction of how to work and how to deal with the application. For organization reasons, we will create a folder within our application files called config, inside that folder we will create the following files :

requirements.txt : which contains all our Django application libraries requirements with their versions.

which contains all our Django application libraries requirements with their versions. gunicorn_config.py : which contains Gunicorn configurations.

: which contains Gunicorn configurations. nginx.conf : the same for Nginx.

: the same for Nginx. supervisor.conf : same for Supervisord.

Let’s start with the first file config/requirements.txt

As you can see, It is always recommended to specify the wanted version of each library in order to avoid build errors if some breaking changes happened in one of them.

About the Gunicorn config file, it is pretty simple

Ofc, we can add more config, but for this example we are concerned only by the basic configuration for the first production run. You can find and learn more about it here.

Now, it is Nginx turn, its config file will be like the following

By this configuration, we’ve told Nginx to listen to all requests coming to the server via the port 80 (If you are using SSL certificate you will need to add the 443 listener as well). Moreover, if the request contains a /static will be redirected to our application’s static content, otherwise, it will be redirected to the main application which in running for now in the 8000

Note : in my application I refer to static files endpoint like that, you can change it if you have other configuration, however, /static is the standard one .

Last but not the least, the supervisor configuration. As we said before, the main function of the supervisord is to run our services similarly, in order to do that the following configuration will be needed.

So by this configuration, we are running bothe Nginx and Gunicorn with supervisord as manager. Also, we can add whatever we need to be run as a service within supervisord’s config, for instance, in this sample we’ve run celery as well.

Finally, now we need to make a dockerfile that grab all those configurations and build one executable docker image for our application.

So let’s walk step by step on what this hell of dockerfile doing. First of all, it is installing in a Ubuntu version the basic libraries that it will be needed by our application including Nginx and Supervisor. Then, it will copy our configurations to their places in the new system after disabling the daemon from Nginx.

After changing the working directory, it will install all our application requirements (that we’ve listed previously), then it runs the migrations if any. Finally, we run supervisor which is going to run all other services.

Now all what we need is building our docker image and run a container from it, using the following commands after going to the project files:

docker build -t our_application . docker run -p 80:80 --restart=always --name=our_app_conatiner our_applciation

Feel free to ask me anything, I would love to answer your questions and learn from each other.

Thanks for reading.