← Back to list

Dockerize Django Like a Pro — The Production Setup Every Developer Should Know — Episode 4

Stop running Django the old way. Learn the clean, production-style Docker workflow used by modern teams — simple, reproducible, and ready…

J3 in Jungletronics · 2026-06-27 18:31 · 0 claps · 6.3 min read paywalled
#docker #docker-compose #dockerfiles #django #how-to
Open on Medium ↗
Wiki topics: 🌐 · Web Development ☁️ · DevOps & Cloud 👗 · Fashion 🏃 · Running & Endurance

Dockerize Django Like a Pro — The Production Setup Every Developer Should Know — Episode 4

Stop running Django the old way. Learn the clean, production-style Docker workflow used by modern teams — simple, reproducible, and ready for real-world deployment

At this point, our project is still a bare-bones Django application. We’re only on Episode 4, so we’ve kept things intentionally simple. So far, we’ve created a basic Task model and configured the Django Admin using the default admin user. Nothing fancy yet.

Now it’s time to take the next step and introduce Docker. Even though our application is small, learning to containerize it from the beginning will help you build projects that are easier to develop, share, and deploy as they grow.

GitHub Repo

GitHub Repo

I’ll guide you step-by-step with a simple, production-style Docker setup.

If this is your first time following this series, start with 👉 Episode 0.

If this is your first time following this series, start with 👉 Episode 0.

Get Started from Previews Episode:

mkdir test
cd test

git clone https://github.com/giljr/python.git

cd python

# From there, check out the desired course version:

# Episode 4
git switch --detach django_v0.4
cd django/4

Or From Scratch:

# Clone the project
git clone <repository-url>
cd <project>

# Create the virtual environment
python3 -m venv env

# Activate it
source env/bin/activate

# Verify the virtual environment
which python
python --version

# Upgrade pip
python -m pip install --upgrade pip

# Install dependencies
python -m pip install -r requirements.txt

# (Optional) Verify Django
python -m django --version

# Apply database migrations
cd first_project
python manage.py migrate

# Start the development server
python manage.py runserver

Expected verification

which python
# /path/to/project/env/bin/python

python --version
# Python 3.x.x

python -m django --version
# 5.x.x

🐳 1. What you are building

You will containerize:

  • Django app
  • Gunicorn (production server)
  • (optional later: PostgreSQL)
  • Static files handling

📁 2. Project structure (important)

Inside your Django project root folder:

first_project/
├── manage.py
├── first_project/
├── first_app/
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── .dockerignore

📦 3. Create requirements.txt

Inside your root:

pip freeze > requirements.txt

Make sure it includes at least:

Django
gunicorn

🐳 4. Create Dockerfile

Create a file named:

touch Dockerfile

Paste:

FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
# Install dependencies
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
# Copy project
COPY . /app/
# Expose port
EXPOSE 8000
# Run server (production style)
CMD ["gunicorn", "first_project.wsgi:application", "--bind", "0.0.0.0:8000"]

🚫 5. Create .dockerignore

touch .dockerignore

Add:

env
__pycache__
*.pyc
db.sqlite3
.git

🧪 6. Build Docker image

Run:

docker build -t django-app .

🚀 7. Run container

docker run -p 8000:8000 django-app

Now open:

http://127.0.0.1:8000

Error:

🧠 Why this happens

Django has a safety setting:

first_project/settings.py

ALLOWED_HOSTS

It prevents HTTP Host header attacks.

Right now Django is rejecting:

0.0.0.0

🚀 Fix (quick dev solution)

If you want cleaner practice, use:

ALLOWED_HOSTS = ["localhost", "127.0.0.1"]

AND when running Docker, you can also add:

ALLOWED_HOSTS = ["localhost", "127.0.0.1", "0.0.0.0"]

🔁 After fix

Restart your container:

docker run -p 8000:8000 django-app

Everything should work fine!

⚙️ 8. (Recommended) Add docker-compose

Now create:

touch docker-compose.yml

Basic version:

services:
  web:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    command: gunicorn first_project.wsgi:application --bind 0.0.0.0:8000

Run:

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker compose up --build

Now open:

http://127.0.0.1:8000

🧠 9. Why this setup is “real production style”

You now have:

✔ isolated environment (no Python dependency issues) ✔ reproducible builds ✔ same setup on any server ✔ Gunicorn instead of Django dev server ✔ ready for cloud deployment

🔥 10. Next upgrade (highly recommended)

If you want to go pro-level next step, I can help you add:

🧱 PostgreSQL container

replace SQLite (production standard)

🌍 Nginx reverse proxy

real web server layer

🔐 Environment variables (.env)

secure secrets (SECRET_KEY, DB password)

☁️ Deploy to cloud

DigitalOcean / AWS / Render

Note ¹

No Python

If Python is not installed by default anymore (or only python3 exists)

✅ Fix (recommended way)

Install Python 3 properly:

sudo apt update
sudo apt install python3 python3-venv python3-pip -y

Then check:

python3 --version

You should see something like:

Python 3.xx.x

⚡ Optional: make python work like python3

If you want the old behavior:

sudo apt install python-is-python3 -y

Then:

python --version

will work normally.

🧪 Create your virtual environment

Use python:

python -m venv env

Activate it:

source env/bin/activate

Now your prompt will change to:

(env) j3@DESENV70:~

This means Docker is not available inside your WSL Ubuntu yet.

Most likely:

  • ✅ WSL is installed
  • ✅ Ubuntu 24.04 is running
  • ❌ Docker Desktop is not installed on Windows, or
  • ❌ WSL integration is disabled for Ubuntu-24.04

Step 1: Check if Docker Desktop is installed

In PowerShell:

docker --version

If you get something like:

Docker version 28.x.x

Docker Desktop is installed.

If you get:

'docker' is not recognized...

Then Docker Desktop is not installed.

Download and install:

Docker Desktop

Step 2: Enable WSL Integration

Open Docker Desktop:

Settings
  → Resources
    → WSL Integration

Enable:

☑ Enable integration with my default WSL distro
☑ Ubuntu-24.04

Click:

Apply & Restart

Step 3: Restart WSL

In PowerShell:

wsl --shutdown

Then start Ubuntu again:

wsl

Step 4: Verify Docker from Ubuntu

Inside Ubuntu:

docker --version

Expected:

Docker version 28.x.x

Also test:

docker run hello-world

Expected:

Hello from Docker!

Step 5: Build your Django image

Return to your project directory:

cd ~/projetos/python/django/1/first_project

Build:

docker build -t django-app .

Run:

docker run -p 8000:8000 django-app

Then open:

http://localhost:8000

Alternative: Install Docker Engine directly inside WSL

You can also install Docker completely inside Ubuntu without Docker Desktop. This is common on Linux servers and VPSs, but for local Windows development, Docker Desktop + WSL integration is usually easier.

First tell me what this command returns in PowerShell:

docker --version

That will tell us whether Docker Desktop is already installed or not.

Run:

sudo apt install util-linux-extra
newgrp docker
  1. The Jungletronics Environment Cleanup Script

When switching between projects or resetting the environment, Jungletronics frequently utilizes a quick, aggressive cleanup chain to wipe the active Docker footprint:

Clean up all Docker

# Gracefully shut down active compose services
docker compose down

# Force-stop all local containers
docker stop $(docker ps -a -q)

# Delete all local containers
docker rm $(docker ps -a -q)

# Wipe all unused cached Docker volumes 
docker volume rm $(docker volume ls -q)

# Delete targeted app-specific virtual bridges
docker network rm <your_network_name>

The essential Docker and Docker Compose commands featured throughout Jungletronics’ software architecture projects (such as FinanceApp, Rails Workstations, and PHP/Node/MySQL stacks) center on ecosystem setup, workflow execution, and environment cleanup. [1, 2, 3]

  1. The Jungletronics Environment Cleanup Script

When switching between projects or resetting the environment, Jungletronics frequently utilizes a quick, aggressive cleanup chain to wipe the active Docker footprint: [1]

bash

# Gracefully shut down active compose services
docker compose down

# Force-stop all local containers
docker stop $(docker ps -a -q)
# Delete all local containers
docker rm $(docker ps -a -q)
# Wipe all unused cached Docker volumes 
docker volume rm $(docker volume ls -q)
# Delete targeted app-specific virtual bridges
docker network rm <your_network_name>
  1. Service Management (Docker Compose)

Jungletronics relies heavily on docker compose to bind backends (e.g., Ruby on Rails, Node.js) directly to database dependencies (e.g., PostgreSQL, MySQL): [1, 2]

  • **docker compose up --build**: Combines image generation and container instantiation into a single step.
  • **docker compose down**: Stops running multi-container applications and tears down networks. [1, 2, 3, 4, 5]
  1. Image Building & Interaction

When spinning up standalone configurations or manual images during initial setups: [1]

  • **docker build -t <image-name> -f <path-to-Dockerfile> .**: Builds custom tagged images from deep nested project paths (e.g., api/db/Dockerfile).
  • **docker run -d -P -v $(pwd):/jungle --name railscontainer <image>**: Spins up background applications mapping current directories directly to a /jungle mount workspace inside the container.
  • **docker exec -it <container-name> <command>**: Drops you directly into live container environments to troubleshoot or issue framework commands (e.g., opening a Rails console or inspecting logs). [1, 2, 3]
  1. Inspection and Debugging

To track asset mapping, configuration drift, and container health within your terminal: [1, 2]

  • **docker ps -a**: Lists every container on the system along with its explicit statuses and mapped internal ports.
  • **docker inspect <container-name> | grep "IPAddress"**: Directly extracts targeted network configuration data from container definitions.
  • **docker run hello-world**: Test routine used to verify if the underlying Ubuntu Docker Engine or WSL2 layer is behaving correctly. [1, 2, 3, 4, 5]

Your Next Step

If you are transitioning your project to this environment, start by mapping out a cohesive architecture file. Create a standard docker-compose.yml file in your root workspace using an isolated network bridge (like jungleNet) to let your custom application service talk securely to your underlying database container. [1, 2, 3]


메타데이터
post_id
948c480f4cdc
slug
dockerize-django-like-a-pro-the-production-setup-every-developer-should-know-episode-4-948c480f4cdc
url
https://medium.com/jungletronics/dockerize-django-like-a-pro-the-production-setup-every-developer-should-know-episode-4-948c480f4cdc
canonical_url
https://medium.com/jungletronics/dockerize-django-like-a-pro-the-production-setup-every-developer-should-know-episode-4-948c480f4cdc
author_url
https://medium.com/@jaythree
status
ok
fetched_at
2026-07-09 15:12:33