Come meet the Okteto team at KubeCon NA on October 24-28
RSVP for a demo and swag!

How to Develop Django and Postgres Applications with Docker and Okteto CLI 2.0

Doesn’t it bother you that you cannot build your application and see how it looks and behaves in production when developing it?

If it does, then you have come to the right place. In this article, you will learn how to set up Docker and Docker compose to build a Django image with the Postgres database. You will then learn how to build a Django application on Okteto to view the project in a production environment as you build. For the Django application, to keep things simple, you will build an API for contact lists.


Okteto's Development Environments allow you to develop your applications directly in a Kubernetes cluster. This way you can be sure what you see is what you'll get when you push to production.

Prerequisites

  • Basic understanding of Django framework
  • An Okteto Cloud account (It’s free!)
  • Docker and Docker Compose installed

Initialize Django Project

Before you get started, create a project directory to contain your application:

$ mkdir django-docker-okteto
$ cd django-docker-okteto


Now run the following command to create a new Django project:

$ django-admin startproject contact_list .

Finally, run the following command to create a Django app:

$ python3 manage.py startapp app

Add the app you just created to the settings.py:

INSTALLED_APPS = [
     ...
    'django.contrib.staticfiles',
    'app',
    'rest_framework', #needed to create the API
]

Now, you need to make some more changes to the settings.py file in order for your Django application to accept the Docker compose host and connect with Postgres.

Add the Docker compose host to Django by adding 0.0.0.0 to ALLOWED_HOST in the settings.py file, since that is the host Docker compose runs on.

ALLOWED_HOSTS = ['0.0.0.0']

For the database configuration, delete the DATABASE dictionary you have in your setting.py file and paste the code below. In a later section, you will set the credentials for the environment variables in the Docker compose file.

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.postgresql',
    'HOST': os.environ.get('DB_HOST'),
    'NAME': os.environ.get('DB_NAME'),
    'USER': os.environ.get('DB_USER'),
    'PASSWORD': os.environ.get('DB_PASS'),
  }
}

Import the os module used in the code above by adding import os at the top of your settings.py file.

Creating a Dockerfile to Build the Django Application

Dockerfile is a file where you write instructions of how you want your Docker image to be. You can get started by creating a Dockerfile that will contain the instructions for building your Django application image:

$ touch Dockerfile

Now add the following to the file:

FROM python:3.7-alpine

ENV PYTHONUNBUFFERED 1
RUN mkdir /django-docker-okteto
WORKDIR /django-docker-okteto
COPY . .
RUN apk add --update --no-cache postgresql-client jpeg-dev
RUN apk add --update --no-cache --virtual .tmp-build-deps \\
      gcc libc-dev linux-headers postgresql-dev musl-dev zlib zlib-dev
RUN pip install -r requirements.txt

RUN adduser -D user
USER user

If you are unfamiliar with Docker, here is the description of the instructions.

FROM: This is used at the beginning of every Dockerfile. It is used to tell Docker what image in Docker hub your image should be built under.

ENV: Used to state environment variables.

PYTHONUNBUFFERED 1: tells Python to display all outputs in real-time.

RUN: Used to run terminal commands. In the code above, it is used to create a new directory in the image, and we later use it to install dependencies.

WORKDIR: Used to make a directory a working directory. All commands will be run from the working directory.

COPY: Used to copy files, here it’ll copy files from local directory to working directory in images

Now, create the requirements.txt file that will contain a list of dependencies to run the application. Create the file at the root of your project and input the text below. The Django REST framework will be used to build the API, so it needs to be installed too. psycopg2-binary is required by Django to run the Postgres database.

django==3.1.2
djangorestframework==3.13.1
psycopg2-binary

Building Docker Compose File to Run Django and PostgreSQL

Since you will be using more than one service (Python, Postgres) in this project, it makes more sense to use Docker Compose to manage them. Docker Compose enables you to manage and build and run different Docker images together. In Docker compose, each image is considered a service. To start, create a new file named docker-compose.yaml that will contain the instructions for building your Django application and Postgres image together:

$ touch docker-compose.yaml


Now add the following to the file. Some comments have been added to the file to describe what each step is doing.

# Version of docker-compose to use 
version: "3"

services:
  app: # This is the service for the Django application
    build:
      context: . # Sets the directory containing a Dockerfile .

    # Maps port on the local machine to port on Docker image
    ports:
      - "8080:8080"
      
    volumes: 
    # Copy changes made to the project to your image working directory as changes are made.
      - .:/django-docker-okteto
    
    environment:
      # The environment variable credentials that is needed 
      # in django settings for Postgres to work.
      - DB_HOST=pg
      - DB_NAME=app2
      - DB_USER=postgres3
      - DB_PASS=supersecretpassword
    depends_on:
      - pg

  pg:
    image: postgres:10-alpine # pulling Postgres image from Docker hub
    environment:
      # credentials required by postgres image
      - POSTGRES_DB=app2
      - POSTGRES_USER=postgres3
      - POSTGRES_PASSWORD=supersecretpassword

Build the Application in Okteto

Before you begin this section, install Okteto CLI to use Okteto's Remote Development Environments. After installation, you will be provided with version 2.0^ by default. You can check the version of Okteto you installed by running okteto version.

Set up your Okteto development environment for Django

Deploy your app to Okteto cloud by running the command below. The following command will create the development environment required for your application to run using instructions stated in docker-compose.yaml file.

$ okteto deploy --build

We added the --build flag to force the build of images so the application can run.

Go to Okteto cloud, after the build and deployment are complete you will be provided with the URL you can use to access your application. Open it in a browser, and you will see that your application is running.

Endpoints on the Okteto dashboardEndpoints on the Okteto dashboard

Now run the following command to connect your local machine to Okteto cloud so that it can receive changes made locally in real-time. This command performs an SSH connection to the server running your application on Okteto cloud and provides a watcher service to keep the definition of the original deployment up to date with the mirror deployment.

$ okteto up

Now, any changes you make to your code locally will be updated in the app URL on Okteto. When the update is made, you will see that the changes are automatically synchronized with the application on the cloud, and you can see the effect of your changes in real-time.


Develop Django Application

Here we will build a contact list application to test out the functionalities of Okteto.

Open contact_list/urls.py and add a route to the app you have created by updating the urlpatterns list.

from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app/', include("app.urls"))] #route for new app

Now, open app/models.py and populate it with the code below. The following code contains the database fields for contacts.

from django.db import models

class ContactList(models.Model):
    name = models.CharField(max_length=200)
    phone_number = models.CharField(max_length=200)
    def __str__(self):
        return self.name

Create a new file, app/serializers.py, and paste the following code. The code below converts the data gotten from the database into JSON and back to its original form.

from rest_framework import serializers
from .models import ContactList

class ContactListSerializer(serializers.ModelSerializer):
    class Meta:
        model = ContactList
        fields = ('name', 'phone_number',"id") # fields in the models

Next, create the view for saving and listing out contacts in the database. You can do this by pasting the following code in app/views.py.

from rest_framework import generics
from rest_framework import status
from rest_framework.decorators import api_view
from .serializers import ContactListSerializer
from rest_framework.response import Response
from .models import ContactList

@api_view(['POST'])
def create_contact(request):
        # create coontact
    contact = ContactListSerializer(data=request.data)
    if contact.is_valid():
        contact.save()
        return Response(contact.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

class ContactListView(generics.ListCreateAPIView):
    # list out contacts
    queryset = ContactList.objects.all()
    serializer_class = ContactListSerializer

Finally, create a new file app/urls.py and paste the code below to set the routing for the views.

from . import views
from django.urls import path

urlpatterns = [
    path('create/', views.create_contact, name='create-items'),
    path('list/', views.ContactListView.as_view(), name='view-contacts'),]


Since you have made changes to the model, you need to run the python manage.py makemigrations and python manage.py migrate commands. You should run these commands in the terminal provided to you by Okteto when you run okteto up. After the migrations are complete, run the Django server with the following command:

python manage.py runserver

Now you will be able to access the paths you just created on the endpoint provided by Okteto.


Seeing your changes live at the endpoint provided by OktetoSeeing your changes live at the endpoint provided by Okteto

Conclusion

In this guide, you were able to learn how to set up Docker and Docker compose to build a Django image with the Postgres database. You then went through activating Okteto's development environment and built a Django application on Okteto to view the project in a production environment as you build.

You can utilize the knowledge obtained in this tutorial and improve on it by adding microservices like Redis, Celery, or any other tool you need when building your application.

Muhammed AliView all posts

Maybe It's Time To Rethink How You've Been Developing?

Cloud-Native Applications Need Cloud-Native Development Environments We've seen a tremendous change in the way applications get deployed over the last...

March 09, 2022
Avatar of Arsh SharmaAvatar of Arsh SharmaArsh Sharma

Developing a Rasa chatbot in Okteto

Rasa is a Python framework for training and building an AI-powered chatbot integrated into various platforms. Training and building AI-powered applications...

January 14, 2022
Avatar of Abdulazeez Abdulazeez AdeshinaAvatar of Abdulazeez Abdulazeez AdeshinaAbdulazeez Abdulazeez Adeshina