Development and Deployment of Cookiecutter-Django via Docker

Development and Deployment of Cookiecutter-Django via Docker

by Real Python devops django docker web-dev

Let’s look at how to bootstrap a Django Project pre-loaded with the basic requirements needed in order to quickly get a project up and running. Further, beyond the project structure, most bootstrapped projects also take care of setting up the development and production environment settings, without troubling the user much - so we’ll look at that as well.

Updates:

  • 04/15/2019: Updated to the latest versions of cookiecutter (v1.6.0), cookiecutter-django, Django (v2.0), Docker (v18.09.2), Docker Compose (v1.23.2), and Docker Machine (v0.16.1).

  • 10/04/2016: Updated to the latest versions of cookiecutter (v1.4.0), cookiecutter-django, Django (v1.10.1), Docker (v1.12.1), Docker Compose (v1.8.1), and Docker Machine (v0.8.2).

We’ll be using the popular cookiecutter-django as the bootstrapper for our Django Project along with Docker to manage our application environment.

Let’s begin!

Local Setup

Start by installing cookiecutter globally:

Shell
$ pip install cookiecutter==1.6.0

Now execute the following command to generate a bootstrapped django project:

Shell
$ cookiecutter https://github.com/pydanny/cookiecutter-django.git

This command runs cookiecutter with the cookiecutter-django repo, allowing us to enter project-specific details:

Shell
project_name [My Awesome Project]: django_cookiecutter_docker
project_slug [django_cookiecutter_django]: django_cookiecutter_docker
description [Behold My Awesome Project!]: Tutorial on bootstrapping django projects
author_name [Daniel Roy Greenfeld]: Michael Herman
domain_name [example.com]: realpython.com
email [michael-herman@example.com]: michael@realpython.com
version [0.1.0]: 0.1.0
Select open_source_license:
1 - MIT
2 - BSD
3 - GPLv3
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 5 (1, 2, 3, 4, 5) [1]: 1
timezone [UTC]: UTC
windows [n]: 
use_pycharm [n]: 
use_docker [n]: y
Select postgresql_version:
1 - 10.5
2 - 10.4
3 - 10.3
4 - 10.2
5 - 10.1
6 - 9.6
7 - 9.5
8 - 9.4
9 - 9.3
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 (1, 2, 3, 4, 5, 6, 7, 8, 9) [1]: 1
Select js_task_runner:
1 - None
2 - Gulp
Choose from 1, 2 (1, 2) [1]: 2
Select cloud_provider:
1 - AWS
2 - GCE
Choose from 1, 2 (1, 2) [1]: 
custom_bootstrap_compilation [n]: 
use_compressor [n]: 
use_celery [n]: 
use_mailhog [n]: 
use_sentry [n]: 
use_whitenoise [n]: 
use_heroku [n]: 
use_travisci [n]: 
keep_local_envs_in_vcs [y]: 
debug [n]: 
 [SUCCESS]: Project initialized, keep up the good work!

Project Structure

Take a quick look at the generated project structure, taking specific note of the following directories:

  1. “config” includes all the settings for our local and production environments.
  2. “requirements” contains all the requirement files - base.txt, local.txt, production.txt - which you can make changes to and then install via pip install -r file_name.
  3. “django_cookiecutter_docker” is the main project directory which consists of the “static”, “contrib” and “templates” directories along with the users app containing the models and boilerplate code associated with user authentication.

Some of the services may require environment variables. You can find the environment files for each service in the .envs directory and add the required variables.

Docker Setup

Follow the instructions to install the Docker Engine and the required Docker components - Engine, Machine, and Compose.

Check the versions:

Shell
$ docker --version
Docker version 18.09.2, build 6247962

$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01

$ docker-machine --version
docker-machine version 0.16.1, build cce350d7

Docker Machine

Once installed, create a new Docker host within the root of the newly created Django Project:

Shell
$ docker-machine create --driver virtualbox dev
$ eval $(docker-machine env dev)

NOTE: dev can be named anything you want. For example, if you have more than one development environment, you could name them djangodev1, djangodev2, and so forth.

To view all Machines, run:

Shell
$ docker-machine ls

You can also view the IP of the dev Machine by running:

Shell
$ docker-machine ip dev

Docker Compose

Now we can fire everything up - e.g., Django and Postgres - via Docker Compose:

Shell
$ docker-compose -f local.yml build
$ docker-compose -f local.yml up -d

You may need to add your Docker machines IP (docker-machine ip dev) to the list of ALLOWED_HOSTS in the config/settings/local.py.

Running Windows? Hit this error - Interactive mode is not yet supported on Windows? See this comment.

The first build will take a while. Due to caching, subsequent builds will run much faster.

Sanity Check

Now we can test our Django Project by applying the migrations and then running the server:

Shell
$ docker-compose -f local.yml run django python manage.py makemigrations
$ docker-compose -f local.yml run django python manage.py migrate
$ docker-compose -f local.yml run django python manage.py createsuperuser

Navigate to the dev IP (port 8000) in your browser to view the Project quick start page with debugging mode on and many more development environment oriented features installed and running.

Stop the containers (docker-compose -f local.yml down), initialize a new git repo, commit, and PUSH to GitHub.

Deployment Setup

So, we have successfully set up our Django Project locally using cookiecutter-django and served it up using the traditional manage.py command line utility via Docker.

In this section, we move on to the deployment part, where the role of a web server comes into play. We will be setting up a Docker Machine on a Digital Ocean droplet, with Postgres as our database and Nginx as our web server.

Along with this, we will be making use of gunicorn instead of Django’s single-threaded development server to run the server process.

Why Nginx?

Apart from being a high-performance HTTP server, which almost every good web server out in the market is, Nginx has some really good features that make it stand out from the rest - namely that it:

  • Can couple as a reverse proxy server.
  • Can host more than one site.
  • Has an asynchronous way of handling web requests, which means that since it doesn’t rely on threads to handle web requests, it has a higher performance while handling multiple requests.

Why Gunicorn?

Gunicorn is a Python WSGI HTTP server that can be easily customized and provides better performance in terms of reliability than Django’s single-threaded development server within production environments.

Digital Ocean Setup

We will be using a Digital Ocean server for this tutorial. After you sign up (if necessary), generate a Personal Access Token, and then run the following command:

Shell
$ docker-machine create \
-d digitalocean \
--digitalocean-access-token ADD_YOUR_TOKEN_HERE \
prod

This should only take few minutes to provision the Digital Ocean droplet and set up a new Docker Machine called prod. While you wait, navigate to the Digital Ocean Control Panel; you should see a new droplet being created, again, called prod.

Once done, there should now be two machines running, one locally (dev) and one on Digital Ocean (prod). Run docker-machine ls to confirm:

Shell
NAME   ACTIVE   DRIVER         STATE     URL                         SWARM   DOCKER     ERRORS
dev    *        virtualbox     Running   tcp://192.168.99.100:2376           v18.09.2
prod   -        digitalocean   Running   tcp://104.131.50.131:2376           v18.09.2

Set prod as the active machine and then load the Docker environment into the shell:

Shell
$ eval $(docker-machine env prod)

Docker Compose (take 2)

Within .envs/.production/.django update the DJANGO_ALLOWED_HOSTS variable to match the Digital Ocean IP address - i.e., DJANGO_ALLOWED_HOSTS=104.131.50.131.

Now we can create the build and then fire up the services in the cloud:

Shell
$ docker-compose -f production.yml build
$ docker-compose -f production.yml up -d

Sanity Check (take 2)

Apply all the migrations:

Shell
$ docker-compose run django python manage.py makemigrations
$ docker-compose run django python manage.py migrate

That’s it!

Now just visit your server’s IP address, associated with the Digital Ocean droplet, and view it in the browser.

You should be good to go.


For further reference just grab the code from the repository. Thanks a lot for reading! Looking forward to your questions.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About The Team

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning