Build Django REST Project in Docker

Build Django REST Project in Docker

Introduction

This is a tutorial to show how we can build a Django Rest Project and Dockerize it in Docker container. Here I will be building a Django project first and then dockerize it to a container... This is the good practice who is new to Django and docker.

Prerequisite:

  • Python version 3+
  • Pip
  • PyCharm (or any other IDE support Python)

    Create Django Project

    Here I'm working on Linux OS, which already comes with Python pre-installed. If Window OS need to install python, recommended to install from windows store.

Steps:

Create a folder. (eg: blog) Open the created folder (blog) in PyCharm IDE. Open Terminal window from bottom of the Application or click Alt+F12 (shortcut).

In the Terminal type: virtualenv venv

A folder named "venv" will be installed and following some python packages will be installed in the folder. Here we installed the virtual environment for the project. Note: virtual environment is created for temporary purpose only, while dockerizing the project, we won't be needing it anymore.

Let's Activate the Environment by executing the command: . venv/bin/activate

Screenshot from 2022-10-27 12-25-43.png

By this time, we can see (venv) is appended in the cursor. It's is a way to identifying that its current environment.

Now lets create a file requirements.txt file. Its a standard procedure to list the required packages to run the project. List of Packages required:

Django==4.1.1
djangorestframework==3.13.1
django-cors-headers==3.13.0

After Copied to the packages to requirements file, Run the command: pip install -r requirements.txt

The Package will be installed in the Environment. Now Let's create the Project by running the command: django-admin startproject blogpost The Project will be created and to create an app in the project:

cd blogpost
python manage.py startapp blogapp

By this Stage, the Project and app is created, Some extra tweak is required to run the project: In the settings.py file ( file used to configure the project) add:

    "rest_framework",
    "blogapp",

in Intalled app list eg:

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "rest_framework",
    "blogapp",
]

"rest_framework" is a build-in app in order to use for rest APIs "blogapp" is the app just created, where we are going to build the APIs.

Now in the urls.py file ( file used to list the urls) add: from django.urls import path, include for the import and path('', include('blogapp.urls')) in the urlpatterns list eg:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path(''", include('blogapp.urls'))
]

here we including the app blogapp's urls to the project url list. So in the blogapp folder, we need to create a file urls.py and add:

from django.urls import path
from . import views as blogview
urlpatterns = [
    path('', blogview.HomeView.as_view(), name='home')
]

We are using Class based view, which is industry standard as in order to represent as_view() is used. Now lets just simply create a function in views.py file

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response


# Create your views here.
class HomeView(APIView):
    def get(self, request):
        return Response("hello")

The Project setup is completed. Run Command:

 python manage.py migrate
 python manage.py runserver

to run the project and project will start and http://127.0.0.1:8000 will be available.

Dockerizing the Project

Now that the Project is ready, We can now dockerize the project.

Prerequisite:

  • Docker
  • docker-compose

For Linux OS:

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

For Windows OS refer:

https://docs.docker.com/desktop/install/windows-install/

Steps:

Completing the installation, create a file docker-compose.yml in the "blog" folder and paste the content:

version: '3.8'

services:
  web:
    build: ./app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app/:/usr/src/app/
    stdin_open: true
    tty: true
    ports:
      - 8000:8000
    env_file:
      - ./.env.dev
    depends_on:
      - db
  db:
    image: postgres:14.4-alpine
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=blog
    ports:
      - 6200:5432

volumes:
  postgres-data:

then create a file "Dockerfile" with no extension and "entrypoint.sh" in the folder where manage.py file exists. Paste the content in Dockerfile:

# pull official base image
FROM python:3.8.5-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev libffi-dev

# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
RUN apk --no-cache add \
    icu-dev \
    gettext \
    gettext-dev

## copy entrypoint.sh
COPY ./entrypoint.sh .
RUN sed -i 's/\r$//g' /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh

# copy project
COPY . .

# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

Paste the content in entrypoint.sh:

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi
mkdir -p logs
exec "$@"

Note: Here we are creating container for Postgre DB which is not configure in the project, which is optional

The Docker is ready to Build by the command:

docker-compose up --build

The build will start and server will be hosted on url: http://0.0.0.0:8000/

Screenshot from 2022-10-27 14-19-51.png