Table of Contents

Creating a Django Development Environment using Docker

This post walks you through the steps that could be used to set up a development environment for working on your Django projects.

Set up the base project structure

Firstly, create a new working directory, install Django and create a new Django project and app.

$ mkdir django-dev && cd django-dev
$ mkdir app && cd app
$ python3.9 -m venv venv
$ source venv/bin/activate
(venv)$ pip install django==3.1.5
(venv)$ django-admin.py startproject django_project .  # Don't forget the dot('.') at the end
(venv)$ python manage.py startapp django_app

Then add the app to the INSTALLED_APPS setting in the settings.py file inside django_project:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_app', # new app
]

Now, apply all the migrations to the database:

(venv)$ python manage.py migrate

Verify that the sqlite3 database is created:

(venv)$ sqlite3 db.sqlite3 
SQLite version 3.26.0 2018-12-01 12:34:55
Enter ".help" for usage hints.
sqlite> .tables
auth_group                  auth_user_user_permissions
auth_group_permissions      django_admin_log          
auth_permission             django_content_type       
auth_user                   django_migrations         
auth_user_groups            django_session            
sqlite> .exit

Create a new superuser and run the Django development server:

(venv)$ python manage.py createsuperuser
(venv)$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
...
...
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Use a browser and go to http://localhost:8000/ to see the Django welcome page. Confirm that you are able to log in to the Django admin at http://localhost:8000/admin/ using the superuser credentials you created above. Quit the server using Ctrl-C. Exit the virtual environment and remove the virtual environment directory (venv) as well.

Then, inside the "app" directory, create a requirements.txt with the following content:

Django==3.1.5

If you have been following the above steps, you should now have a directory structure like below:

$ tree .
└── django-dev
    └── app
        ├── db.sqlite3
        ├── django_app
           ├── admin.py
           ├── apps.py
           ├── __init__.py
           ├── migrations
              ├── __init__.py
           ├── models.py
           ├── tests.py
           └── views.py
        ├── django_project
           ├── asgi.py
           ├── __init__.py
           ├── settings.py
           ├── urls.py
           └── wsgi.py
        ├── manage.py
        └── requirements.txt

Containerize the Django app

Prerequisite: Make sure that you have Docker and Docker Compose installed:

$ docker -v
Docker version 20.10.1, build 831ebea
$ docker-compose -v
docker-compose version 1.27.4, build 40524192

If you don't have the above installed, please install or upgrade.

Then, add a Dockerfile to the "app" directory with the following contents:

# Pull official base image
FROM python:3.9.1-slim-buster

# Set working directory
WORKDIR /usr/src/app

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# Add the app
COPY . .
  1. The base image is a slim-buster-based Docker image for Python 3.9.1.
  2. Set the working directory to /usr/src/app for the container.
  3. Set two environment variables:
    1. PYTHONDONTWRITEBYTECODE - This tells Python not to write pyc files in the container.
    2. PYTHONUNBUFFERED - This tells Python not to buffer standard output (stdout) and standard error (stderr).
  4. Update Pip, copy the requirements.txt into the working directory and install the dependencies from the file.
  5. Finally, copy the entire project itself into the working directory.

To prevent some files and folders from getting copied over to the final image, add a .dockerignore file to the "app" directory with the following contents:

venv
.dockerignore
Dockerfile

Then, add a docker-compose.yml file into the project root:

version: '3.8'

services:
  django-app:
    build: ./app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app/:/usr/src/app/
    ports:
      - 8008:8000
    environment: 
      - DEBUG=1
      - SECRET_KEY=mysecretkey
      - DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

In a nutshell, the above config does the following:

  1. Create a service called django-app from the Dockerfile.
  2. Run the Django development server when the container starts.
  3. The volume is used to mount the code into the container. This is essential to make sure that the container gets updated whenever you make changes to the source code. Otherwise, the image would have to be rebuilt every time a change made to the source code needs to go into the container.
  4. Binds the port 8008 on the host machine to port 8000 inside the container.
  5. Sets a few environment variables to be passed into the container.

Then update the SECRET_KEY, DEBUG and ALLOWED_HOSTS variables in the settings.py file inside the django_project directory:

import os

SECRET_KEY = os.environ.get("SECRET_KEY")
DEBUG = int(os.environ.get("DEBUG", default=0))
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split()

Now, build the image:

$ docker-compose build

Once the build is completed, start a container from the image in the detached mode:

$ docker-compose up -d

Make sure the container is up and running:

$ docker-compose ps

Got to http://localhost:8008/ and confirm that you are able to see the Django welcome page.

That's it. Congratulations! Your Django development environment is now ready. You can start making changes to your project and app and those are going to reflect inside the container.

Note: If you add new dependencies to the requirement.txt file, make sure to rebuild the image:

$ docker-compose up -d --build

To bring down the container, do this:

$ docker-compose down

Conclusion

In the post, we created a base project structure for the Django project and then we containerized the Django app. Bringing up the development environment for a web framework like Django could be intimidating. Hopefully, I have made that task a bit easier for you.

That's it, my readers, until next time, happy coding!

Share this post:

Leave a comment

Similar Posts


Everything is hard before it is easy.