Kubernetes Development Blog
  • Docs
  • GitHub
  • Blog
  • Install

›Recent Posts

Recent Posts

  • DevOps and the Cloud: Tools and Technologies for Forward Looking DevOps Teams
  • The Missing Kubernetes Platform for Developers
  • How to Give Developers Access to Kubernetes During Development
  • How to deal with computing resource cost for Kubernetes-based development
  • Why Cloud Development Could (Finally) Become the New Standard

Deploy Django Projects to Kubernetes

October 18, 2019

Lukas Gentele

Lukas Gentele

Scalable Django Deployment using Kubernetes and DevSpace.

This tutorial is meant to be a guide for Django developers who want to explore Kubernetes and boost their productivity when building and deploying Django projects using Kubernetes. This tutorial is independent of any cloud platform. Everything works with any Kubernetes cluster, no matter if it is a local single-node cluster created with minikube or Docker Desktop, if it's a fully managed cluster in GKE, AKS or EKS, or if it is a vCluster created with loft

1. Create Django Project

If you already have a Django project, you can skip this step but make sure you have a requirements.txt within your project's root directory (run pip freeze > requirements.txt to create it).

Before creating a new Django project, let's define a variable with the directory that we want our Django project to be located in:

PROJECT_DIR=/c/Users/[username]/django  # for git-bash on windows
PROJECT_DIR=/home/[username]/django     # for unix-based systems (mac, linux)

If you are using the legacy Docker Toolbox (e.g. because you are using Windows Home Edition), your $PROJECT_DIR needs to be inside your user's home directory, e.g. /c/Users/[username].

If you are using Docker Desktop on Windows, make sure you have the drive that your project should be on marked as Shared Drive in the Docker settings.

We should also define a variable for the project name:

PROJECT_NAME=mysite # warning: Django only allows characters a-z, no -, space or anything else

Now, we are creating a new Django project using Docker:

mkdir $PROJECT_DIR
docker run --rm -v /$PROJECT_DIR:/app -w //app python bash -c "pip install django && django-admin startproject $PROJECT_NAME && pip freeze > $PROJECT_NAME/requirements.txt"
cd $PROJECT_DIR/$PROJECT_NAME

Great! We are all set. Now, let's containerize our Django project.

2. Containerize Project

Of course, we could manually create a Dockerfile, Kubernetes manifests or even a Helm chart but that is a lot of work and quite error-prone. So, let's automate containerizing our Django project using DevSpace. DevSpace is a cloud-native dev tool for Kubernetes. It is open-source and you can install it from GitHub.

After DevSpace is installed on your computer, you can containerize your Django project using this command:

devspace init

DevSpace will ask a couple of questions. Make sure you tell it that this is:

  • a project that uses python as programming language
  • a project that listens on port 8000

If you are not sure about the Docker registry or other questions, just choose the default option that DevSpace recommends for you.

After we containerized the project, DevSpace added a Dockerfile to the project. Change the last line in this Dockerfile from:

CMD ["app.py"]

to:

CMD ["manage.py", "runserver"]

Now, we are ready to deploy the Django project to Kubernetes.

3. Choose Kubernetes Cluster

For this step, you need access to Kubernetes. If you do not have a cluster yet, you can create one locally, e.g. with minikube, start a new cluster in a public cloud or create a virtual cluster with loft (if your team has a cluster already connected to loft).

When you have access to a Kubernetes cluster, tell DevSpace which namespace to deploy the project to using this command:

devspace use namespace [my-namespace]

DevSpace will create this namespace during the deployment, if it does not exists yet. Make sure you are in the right kube-context before deploying the project.

4. Develop

Before we deploy our project in a production-like fashion, let's start the development mode first:

devspace dev

This command tells DevSpace to:

  1. Build a Docker image based on the Dockerfile
  2. Tag and push this image to a Docker registry (e.g. Docker Hub)
  3. Deploy a Helm chart with a Kubernetes deployment for our Django app
  4. Start port-forwarding to access the application on localhost (+ open in browser)
  5. Stream the logs of your containers
  6. Watch for file changes and restart the app if any file changes

You can customize what happens within the DevSpace config file devspace.yaml which devspace init created for your project.

After devspace dev has successfully deployed, you should see a log output of Django inside the command-line and the browser will open up with our Django site showing a beautiful welcome page:

Django Welcome Page - If you see this one, you're doing everything right so far!

In addition to deploying our Django application to Kubernetes, the devspace dev command also starts a powerful development UI which runs on localhost and is available as long as the devspace dev command is running.

You should see a log statement similar to this one in the output of devspace dev:

#########################################################
[info]   DevSpace UI available at: http://localhost:8090
#########################################################

So go ahead and check out the DevSpace UI in your browser! You can use it to see the container and pod status of your deployments as well as to stream logs and open interactive terminal sessions for every container. It should look like in this screencast:

DevSpace: Kubernetes Development UI - Screencast

Now, it's time to create the /pages folder. Run this command to create it:

devspace enter python manage.py startapp pages

After adding the pages folder, we need to add pages.apps.PagesConfig to the INSTALLED_APPS array within $PROJECT_NAME/settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pages.apps.PagesConfig',
]

Great! Time to add a Hello World page ;)

Add 'Hello World' View

Edit the file $PROJECT_NAME/pages/views.py, so that it looks like this:

from django.http import HttpResponse

def homePageView(request):
    return HttpResponse('Hello, World!')

Now, create the file $PROJECT_NAME/pages/urls.py with the following content:

from django.urls import path

from .views import homePageView

urlpatterns = [
    path('', homePageView, name='home')
]

And the last step for adding our Hello World page is to change the code in $PROJECT_NAME/urls.py from:

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

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

to:

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

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

That's it! Now, you can reload the browser and you will see that DevSpace updated your Django app in real-time - no need to deploy your project because DevSpace uses hot reloading to update your running containers.

Try it yourself:

  1. Change your "Hello World!" statement inside: $PROJECT_NAME/pages/views.py
  2. Reload the browser and see how the change is taking effect immediately.
Subscribe to learn more about Kubernetes!
Subscriptions

Bonus: Add PostgreSQL Database

Before you can add a postgres database, make sure you terminate devspace dev, e.g. using CTRL+C.

First, we need to add the postgres driver for Python to our requirements.txt using this command:

docker run --rm -v /$PROJECT_DIR:/app -w //app python bash -c "pip install psycopg2 && pip freeze | grep psycopg2 >> $PROJECT_NAME/requirements.txt"

Now, we need to tell DevSpace that we also want to deploy a PostgreSQL database. To do this, we need to change the deployments section within our devspace.yaml from:

deployments:
- name: mysite                                      # this line may be different for you
  helm:
    componentChart: true
    values:
      containers:
      - image: dscr.io/${DEVSPACE_USERNAME}/mysite  # this line may be different for you
      service:
        ports:
        - port: 8000

to:

deployments:
- name: database
  helm:
    chart:
      name: stable/postgresql
      version: "6.5.9"
    values:
      postgresqlDatabase: "db_mysite"
      postgresqlUsername: "db_user"
      postgresqlPassword: ${DB_PASSWORD}
- name: mysite                                      # this line may be different for you
  helm:
    componentChart: true
    values:
      containers:
      - image: dscr.io/${DEVSPACE_USERNAME}/mysite  # this line may be different for you
        env:
        - name: DB_HOST
          value: "database-postgresql"
        - name: DB_NAME
          value: "db_mysite"
        - name: DB_USER
          value: "db_user"
        - name: DB_PASSWORD
          value: ${DB_PASSWORD}
      service:
        ports:
        - port: 8000

As you can see, we can use the values section in the configuration of this postgresql deployment to set the database name, user and password. Keep in mind that unlike most other config options these settings shown above are only used the very first time you deploy the database. That means that after deploying the database for the first time, you will need to connect to the database and change username/password etc. manually if you want to change this later on.

To view a list of all available config options (i.e. values) for this mysql deployment, take a look at the documentation of this Helm chart on GitHub.

If we deploy the project again, DevSpace will now start a PostgreSQL database container. But before we do this, we should configure our Django project to connect to the database. So change the $PROJECT_NAME/settings.py from:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

to:

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_PASSWORD'),
    }
}

Now, let's redeploy our Django project using this command:

devspace dev -b

The first time you run devspace dev after this change, DevSpace will ask you to define a database password that is used for the variable DB_PASSWORD.

Notice the -b flag which is a shortcut for --force-rebuild. It tells DevSpace that we do not want to use hot reloading and instead rebuild the Docker image and redeploy the project completely. This is often useful when important settings change that cannot be updated using hot reloading, e.g. settings.py.

When you see the logs again, you can either abort devspace dev or you can open an additional terminal and check the logs of the PostgreSQL database to make sure it is ready before you continue. You can check if it is ready by taking a look at the logs via:

devspace logs -f

After adding the database connection to the Django app, we need to run a migration. We can do this using the following command:

devspace enter python manage.py migrate

DevSpace will ask you in which container the migration should be executed. Make sure to select the the Django application.

5. Deploy

If you are done building your application and you want to publish it, you should not do it via devspace dev which is meant for development. For the production-like deployment, you can use the following command:

devspace deploy

After successfully deploying Django to Kubernetes, you can make the project available on a public URL or access it via localhost (using port-forwarding similar to devspace dev) by running:

devspace open

What's next?

I hope this tutorial helps a lot of people to get started with deploying Django projects on Kubernetes. It is very hard to cover every detail in one tutorial and I want to write a follow-up on this article. If you have any questions or things you want me to write about in my next article, reach out via twitter @LukasGentele or send me an email via: lg AT devspace.cloud Also don't forget to subscribe below to get an email when my next article is online.

Tweet
Recent Posts
  • 1. Create Django Project
  • 2. Containerize Project
  • 3. Choose Kubernetes Cluster
  • 4. Develop
    • Add 'Hello World' View
    • Bonus: Add PostgreSQL Database
  • 5. Deploy
  • What's next?
Star
Don't miss new blog posts and subscribe here:
Subscriptions