Skip to main content

Command Palette

Search for a command to run...

Containerising a simple Django application with Docker

Updated
•7 min read•View as Markdown

In this article, we'll take you on a hands-on journey to containerize a Django application from scratch. Whether you're new to Django or Docker, we'll break down everything — from understanding the core structure of a Django project to building your own Docker image and running your app inside a container. Let’s turn your Django project into a portable, production-ready container — step by step!

1) Understanding the basics of a django project :

  1. Install python, django in ur terminal.

  2. And then run the following commands:

django-admin startproject myproject
cd myproject
  1. This will create myproject folder and the structure of myproject looks like:

🔧 STRUCTURE :

myproject/
├── manage.py
├── myproject/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   └── wsgi.py
  1. Now lets explore all components in myproject / myproject folder:

Project Folder: myproject/

This contains global settings for the project.

a. __init__.py

  • Makes this folder a Python package.

b. settings.py

  • Contains project-wide settings:

    • INSTALLED_APPS: List of all Django apps.

    • DATABASES: DB connection info.

    • MIDDLEWARE: Middleware stack.

    • TEMPLATES: Template engine config.

    • STATIC_URL, MEDIA_URL: For static/media files.

c. urls.py

  • Main URL configuration file.

  • You route URLs to views here.

  • Can include app-level URLs:

      path('myapp/', include('myapp.urls'))
    

d. asgi.py & wsgi.py

  • Entry points for deployment:

    • wsgi.py is used by WSGI servers like Gunicorn.

    • asgi.py is for ASGI servers like Daphne or Uvicorn (async support).

Now we came to know that myproject / myproject folder is just a settings folder. The actual logic of applications lies in their app folders.

  1. Now in the myproject/ folder to create a app folder with the name myapp/, run this command:
python manage.py startapp myapp

Now the folder structure will be:

🔧 STRUCTURE

myproject/
├── manage.py
├── myproject/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   └── wsgi.py
├── myapp/
│   ├── admin.py
│   ├── apps.py
│   ├── migrations/
│   ├── models.py
│   ├── tests.py
│   ├── views.py
│   ├── urls.py
│   ├── forms.py (optional)
│   └── templates/
│       └── myapp/
│           └── example.html

myapp/ is the folder containing the actual application logic.

  1. The general components in any application folder are:

🔹App Folder: myapp/

This is where your application logic lives.

a. admin.py

  • Registers models to Django admin panel.

b. apps.py

  • App configuration class.

c. migrations/

  • Auto-generated DB migration files.

  • Contains __init__.py and numbered migrations like 0001_initial.py.

d. models.py

  • Defines database models.

  • Example:

      class Student(models.Model):
          name = models.CharField(max_length=100)
    

e. views.py

  • Handles request and response.

  • View functions or class-based views:

      def home(request):
          return render(request, 'myapp/home.html')
    
  • App-specific URL patterns.

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

🔹 4. templates/ and static/

  • Place these outside the app or inside each app.

a. templates/

  • HTML files rendered by views.

  • Follow this structure:

      templates/
      └── myapp/
          └── home.html
    
  • Use {% extends "base.html" %} and {% block content %} to create reusable templates.

b. static/

  • For CSS, JS, images, etc.

      static/
      └── myapp/
          ├── style.css
          └── script.js
    

Add these in settings.py:

STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / "static"]

✅ Best Practice Structure:

myproject/
├── manage.py
├── myproject/
│   └── settings/
│       ├── __init__.py
│       ├── base.py
│       ├── dev.py
│       └── prod.py
├── myapp/
│   ├── models/
│   ├── views/
│   ├── urls.py
│   ├── forms/
│   ├── templates/
│   └── static/
├── templates/
│   └── base.html
├── static/
│   ├── css/
│   ├── js/
│   └── images/
└── requirements.txt

🧠 Summary

PartPurpose
manage.pyEntry point for Django commands
settings.pyAll configurations: DB, static, apps, middleware
urls.pyURL routing
models.pyDefine DB schema
views.pyDefine logic for HTTP requests
templates/Frontend HTML
static/Frontend CSS/JS/Images
migrations/DB schema versioning

✅ 1. Real-world projects usually have multiple apps

Example:

Suppose you're building an e-commerce website, you might split features into multiple apps like:

myproject/
├── users/           # login, registration, profiles
├── products/        # product listings, details
├── cart/            # shopping cart
├── orders/          # order history, payment
├── reviews/         # product reviews and ratings
├── myproject/       # main project settings and URLs
└── manage.py

Each app is a self-contained component responsible for a specific domain of the project.

✅ 2. How to run all these apps ?

manage.py remains your central command-line tool even with multiple apps.

When you run:

python manage.py runserver
  • Django loads all apps listed in INSTALLED_APPS (defined in settings.py).

  • All migrations, views, URLs, models, templates, etc., from each app are registered and active.

Example:

# settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'users',
    'products',
    'cart',
    'orders',
    'reviews',
]

Once listed here, Django manages them together using manage.py.

✅ 3. No matter how many apps you have, single manage.py = All apps run together.

🎯 Sample Project: myshop

We'll create 3 apps:

  • users/ → login, register, profile

  • products/ → product list/detail

  • orders/ → order history, checkout


🗂️ Folder Structure

myshop/
├── manage.py
├── myshop/                # Project settings
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py            # Main URL config
│   └── wsgi.py
├── users/                 # App 1
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── urls.py            # App-specific URLs
│   ├── views.py
│   └── templates/users/
├── products/              # App 2
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── urls.py
│   ├── views.py
│   └── templates/products/
├── orders/                # App 3
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── urls.py
│   ├── views.py
│   └── templates/orders/
└── static/

⚙️ Step-by-step Setup

✅ 1. In settings.py, add all apps

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    # your custom apps
    'users',
    'products',
    'orders',
]

✅ 2. myshop/urls.py → Main URL router

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/', include('users.urls')),
    path('products/', include('products.urls')),
    path('orders/', include('orders.urls')),
]

✅ 3. Each app has its own urls.py

📁 users/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('login/', views.login_view, name='login'),
    path('register/', views.register_view, name='register'),
]

📁 products/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.product_list, name='product_list'),
    path('<int:product_id>/', views.product_detail, name='product_detail'),
]

📁 orders/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('checkout/', views.checkout_view, name='checkout'),
    path('history/', views.order_history, name='order_history'),
]

✅ 4. Sample Views

products/views.py

from django.shortcuts import render

def product_list(request):
    return render(request, 'products/list.html')

def product_detail(request, product_id):
    return render(request, 'products/detail.html')

🚀 How Django maps URLs now:

URLMapped to
/products/products.views.product_list()
/products/5/products.views.product_detail()
/users/login/users.views.login_view()
/orders/checkout/orders.views.checkout_view()

✅ Key Benefits

FeatureResult
Modular URL routingEasy to scale and organize routes
Per-app templatesKeeps frontend code modular
Shared settings & runOne manage.py handles all apps
Clean separationEasier for teams and maintenance

As we understood about the folder structure of django, now lets dive into containerisation.

2) Containerising the application :

  1. For complete basics on docker, https://github.com/iam-veeramalla/Docker-Zero-to-Hero/blob/main/README.md

i) Installing docker:

sudo apt update
sudo apt install docker.io -y
sudo usermod -aG docker ubuntu

i a) ubuntu in 3rd command is username of host machine on which u install docker. To exactly determine the username of ur host, run whoami command.

i b) Restart the host machine to apply changes.

ii) Installing source code and docker file from a github repo:

git clone https://github.com/iam-veeramalla/Docker-Zero-to-Hero.git
cd Docker-Zero-to-Hero/examples/python-web-app
ls

We can see Dockerfile, source code folder and requirements.txt file

iii) With the dockerfile, build an image with docker build . command.

iv) With docker images command, u can see our newly created image with its id, size.

v) Now run the container with docker run -p 8000:8000 -it <image-id>

We can see that the container is running.

M

Nice effort

1

More from this blog

Docker

7 posts