Skip to content

Repository files navigation

🐳 Docker DevOps Project – Django Notes Application

A complete Dockerized Django Notes Application demonstrating containerization, multi-container orchestration, networking, persistent storage, healthchecks, environment configuration, and Nginx reverse proxy.


πŸ“Έ Project Screenshots

πŸš€ 1. Application Output

This screenshot shows the final output of the Django Notes application.

Application Output

πŸ’» 2. VS Code – Project Code

This screenshot shows the project source code and structure in VS Code.

VS Code Project

🐳 3. Docker Image Build Process

This screenshot shows the Docker image being built successfully.

Docker Image Build Process


πŸŽ₯ Reference Video

πŸ“Ί Train with Shubham – Dockerizing Django Application

πŸ”— https://youtu.be/9bSbNNH4Nqw


πŸ“Œ Table of Contents


πŸš€ Project Overview

This project demonstrates how a traditional web application can be converted into a multi-container Docker application.

The application uses:

  • Django for backend/application logic
  • MySQL for persistent application data
  • Nginx as a reverse proxy
  • Docker for containerization
  • Docker Compose for orchestration
  • .env for configuration and database credentials
  • Docker volumes for database persistence
  • Docker healthchecks to verify service readiness

The project follows a simple three-tier architecture:

                    USER / BROWSER
                           |
                           | HTTP :80
                           v
                    +--------------+
                    |    NGINX     |
                    | Reverse Proxy|
                    +--------------+
                           |
                           | HTTP :8000
                           v
                    +--------------+
                    |    DJANGO    |
                    |   Backend    |
                    +--------------+
                           |
                           | MySQL :3306
                           v
                    +--------------+
                    |    MYSQL     |
                    |   Database   |
                    +--------------+
                           |
                           v
                       DB VOLUME

πŸ—οΈ Architecture

The application is divided into three main services:

1. Django

Django is the main application/backend service.

Responsibilities:

  • Runs the Python/Django application
  • Handles application requests
  • Connects to MySQL
  • Runs database migrations
  • Serves the application through Gunicorn

Typical internal port:

8000

2. MySQL

MySQL stores the application's persistent data.

Responsibilities:

  • Store application records
  • Provide database services to Django
  • Persist data through Docker volumes

Typical internal port:

3306

Example configuration:

DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_HOST=db_cont
DB_PORT=3306

db_cont is the Docker container hostname used by Django to reach MySQL. It is not a MySQL account name.


3. Nginx

Nginx acts as the reverse proxy and public entry point.

Responsibilities:

  • Accept browser requests
  • Listen on port 80
  • Forward requests to Django
  • Provide a single public endpoint for the application

Typical flow:

Browser
   ↓
localhost:80
   ↓
Nginx
   ↓
Django:8000
   ↓
MySQL:3306

🧰 Technology Stack

Technology Purpose
Docker Containerization
Docker Compose Multi-container orchestration
Django Backend/application framework
Python Backend programming language
MySQL Database
Nginx Reverse proxy/web server
Gunicorn Django application server
Docker Network Container-to-container communication
Docker Volume Persistent database storage
.env Environment configuration
Docker Scout Image vulnerability scanning

πŸ“ Project Structure

A typical project structure is:

docker-devops-project/
β”‚
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ backend/
β”‚   β”‚   β”œβ”€β”€ manage.py
β”‚   β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”‚   β”œβ”€β”€ <django-project>/
β”‚   β”‚   └── <django-app>/
β”‚   β”‚
β”‚   └── frontend/
β”‚       β”œβ”€β”€ public/
β”‚       └── src/
β”‚
β”œβ”€β”€ nginx/
β”‚   └── nginx.conf
β”‚
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ .env
β”œβ”€β”€ .dockerignore
└── README.md

The exact folder names can vary depending on the repository implementation. Keep this structure aligned with your actual project files.


πŸ”„ How the Application Works

When a user opens:

http://localhost

the request follows this path:

1. Browser
      ↓
2. Nginx :80
      ↓
3. Django/Gunicorn :8000
      ↓
4. Django processes request
      ↓
5. Django communicates with MySQL :3306
      ↓
6. MySQL returns data
      ↓
7. Django returns response
      ↓
8. Nginx sends response to browser

This separation makes the application easier to deploy, maintain, scale, and troubleshoot.


🐳 Docker Components

Dockerfile

The Dockerfile defines how the application image is built.

Typical responsibilities:

  • Select a base image
  • Set the working directory
  • Install dependencies
  • Copy application source code
  • Configure the application
  • Define the startup command

Example conceptual flow:

Base Python Image
       ↓
Install Dependencies
       ↓
Copy Application
       ↓
Configure Environment
       ↓
Run Django/Gunicorn

πŸ” Environment Variables

The .env file stores configuration values outside the application source code.

Example:

DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_PORT=3306
DB_HOST=db_cont

Meaning

Variable Meaning
DB_NAME MySQL database name
DB_USER Database username
DB_PASSWORD Database password
DB_PORT MySQL port
DB_HOST Docker hostname of MySQL

Important

For real production deployments, do not commit passwords or secrets to GitHub.

Use:

.env

and add it to .gitignore:

.env

βš™οΈ Docker Compose

docker-compose.yml is the central blueprint of the application.

It defines:

  • Services
  • Images/builds
  • Ports
  • Environment variables
  • Networks
  • Volumes
  • Dependencies
  • Healthchecks
  • Restart behavior

Example architecture:

services:

  db:
    image: mysql
    container_name: db_cont

  django:
    build: .
    container_name: django_cont

  nginx:
    image: nginx
    container_name: nginx_cont

πŸ—„οΈ Database

The project uses MySQL.

The database is created/configured through the MySQL container environment.

Example:

MYSQL_DATABASE=test_db
MYSQL_ROOT_PASSWORD=root

Django connects using:

DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_HOST=db_cont
DB_PORT=3306

Do I need MySQL installed on Windows?

No.

If MySQL is running inside Docker, you do not need to separately install MySQL on your Windows machine.

You also do not normally need to manually create Django tables.

Django migrations handle application tables:

python manage.py migrate

πŸ”— Docker Networking

Docker Compose creates an internal network for the services.

Containers can communicate using service/container names rather than manually configured IP addresses.

For example:

DB_HOST=db_cont

Django can reach MySQL through:

db_cont:3306

Conceptually:

django_cont
     |
     | Docker Network
     |
     +------> db_cont:3306

This is more reliable than hardcoding a container IP address.


πŸ’Ύ Docker Volumes

Database containers should use persistent storage.

Without a volume:

Container deleted
      ↓
Database data may be lost

With a volume:

Container deleted
      ↓
Volume remains
      ↓
Database data remains

Example:

volumes:
  mysql_data:

and:

services:
  db:
    volumes:
      - mysql_data:/var/lib/mysql

This is especially important for databases.


❀️ Healthchecks

One of the important problems in this project is database startup timing.

MySQL may take several seconds to initialize.

If Django starts immediately:

Django starts
      ↓
Connect to MySQL
      ↓
MySQL not ready
      ↓
Connection error
      ↓
Django exits/restarts

A healthcheck improves this:

MySQL starts
      ↓
Healthcheck
      ↓
MySQL ready
      ↓
Database becomes healthy
      ↓
Django starts
      ↓
Django connects successfully

Example:

healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 5s
  timeout: 5s
  retries: 10

Then Compose can use dependency conditions so Django waits for a healthy database.


🌐 Nginx Reverse Proxy

Nginx provides the public entry point.

Instead of exposing Django directly to users:

User β†’ Django

the architecture uses:

User
  ↓
Nginx
  ↓
Django

Why use Nginx?

  • Reverse proxy
  • Centralized traffic handling
  • Static file serving
  • SSL/TLS termination capability
  • Access control
  • Caching capability
  • Better production architecture
  • Easier future scaling

πŸš€ Setup & Installation

Prerequisites

Install:

  1. Docker Desktop
  2. Git
  3. A code editor such as VS Code

Verify Docker:

docker --version

Verify Compose:

docker compose version

Verify Git:

git --version

πŸ“₯ Clone the Repository

git clone https://github.com/hritikranjan1/django-notes-app.git

Move into the project:

cd django-notes-app

πŸ” Configure .env

Create:

.env

Example:

DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_PORT=3306
DB_HOST=db_cont

Your Compose MySQL configuration must use compatible database credentials.

For example:

MYSQL_DATABASE=test_db
MYSQL_ROOT_PASSWORD=root

Do not expose real production credentials in README files or public repositories.


πŸ—οΈ Build and Start

Recommended modern Docker Compose command:

docker compose up -d --build

This will:

  1. Build the application image
  2. Pull required images
  3. Create networks
  4. Create volumes
  5. Create containers
  6. Start MySQL
  7. Wait for required health conditions
  8. Start Django
  9. Start Nginx

πŸ” Check Running Containers

Run:

docker ps

Expected architecture:

db_cont
django_cont
nginx_cont

Example:

CONTAINER ID   IMAGE        STATUS
xxxxxx         mysql        Up (healthy)
xxxxxx         django_app   Up (healthy)
xxxxxx         nginx        Up

🌍 Access the Application

Through Nginx

Open:

http://localhost

This is the preferred application entry point.

Direct Django access

If port 8000 is exposed:

http://localhost:8000

This bypasses Nginx and is useful for troubleshooting.


βœ… Verify the Application

Test Django

PowerShell:

curl.exe http://localhost:8000

A successful response should contain:

HTTP/1.1 200 OK

or an equivalent successful HTTP response.


Test Nginx

curl.exe http://localhost

Then open:

http://localhost

in a browser.


πŸ—„οΈ Connect to MySQL

If the MySQL container is named:

db_cont

run:

docker exec -it db_cont mysql -uroot -proot

Then:

SHOW DATABASES;

Select the database:

USE test_db;

Check tables:

SHOW TABLES;

Exit:

exit;

πŸ§ͺ Run Django Migrations

Enter the Django container:

docker exec -it django_cont sh

Then:

python manage.py migrate

Check migrations:

python manage.py showmigrations

Exit:

exit

πŸ“œ Logs & Troubleshooting

View all logs

docker compose logs

Follow logs:

docker compose logs -f

Django logs

docker logs django_cont

Follow:

docker logs -f django_cont

MySQL logs

docker logs db_cont

Nginx logs

docker logs nginx_cont

πŸ”Ž Check Container Status

docker compose ps

or:

docker ps

Healthy example:

db_cont       Up (healthy)
django_cont   Up (healthy)
nginx_cont    Up

πŸ›‘ Stop the Project

docker compose down

This stops and removes containers and the Compose network.

Named volumes are normally preserved unless explicitly removed.


▢️ Start Again

After stopping:

docker compose up -d

If code or Docker configuration changed:

docker compose up -d --build

🧹 Remove Containers

docker compose down

To also remove volumes:

docker compose down -v

⚠️ Warning: Removing the database volume can delete persistent database data.

Use down -v carefully.


πŸ”„ Rebuild From Scratch

If you need to rebuild images:

docker compose down
docker compose build --no-cache
docker compose up -d

Do not use down -v unless you intentionally want to remove database volumes.


🧰 Useful Docker Commands

List containers

docker ps

All containers:

docker ps -a

List images

docker images

List volumes

docker volume ls

List networks

docker network ls

Inspect container

docker inspect django_cont

Container shell

docker exec -it django_cont sh

Restart service

docker compose restart django

Stop one service

docker compose stop django

Start one service

docker compose start django

🐞 Common Problems

1. Django cannot connect to MySQL

Error:

django.db.utils.OperationalError:
Can't connect to server on 'db_cont'

Possible reason:

MySQL is still initializing.

Check:

docker compose ps

Then:

docker logs db_cont

Look for:

ready for connections

Healthchecks and depends_on should be configured so Django waits for database readiness.


2. Django container keeps restarting

Check:

docker logs django_cont

Common causes:

  • Database unavailable
  • Incorrect .env
  • Missing Python package
  • Migration failure
  • Incorrect Django settings
  • Incorrect startup command

3. Nginx is running but application does not open

Check:

docker logs nginx_cont

Then:

docker logs django_cont

Test Django directly:

curl.exe http://localhost:8000

If port 8000 works but port 80 does not, investigate the Nginx configuration.


4. Port already in use

If Docker reports:

port is already allocated

find the process using the port.

On Windows:

netstat -ano | findstr :80

For port 8000:

netstat -ano | findstr :8000

5. Database exists but tables are missing

Run:

docker exec -it django_cont python manage.py migrate

Then:

docker exec -it db_cont mysql -uroot -proot

and:

USE test_db;
SHOW TABLES;

6. .env changes are not reflected

After changing environment configuration, recreate/restart the services:

docker compose down
docker compose up -d --build

If required, force recreation:

docker compose up -d --force-recreate

πŸ” Security Best Practices

For learning, values such as:

DB_USER=root
DB_PASSWORD=root

are acceptable.

For production:

  • Do not use the MySQL root account for the application.
  • Use a dedicated database user.
  • Use a strong password.
  • Do not commit .env to Git.
  • Use secrets management.
  • Scan images for vulnerabilities.
  • Keep base images updated.
  • Use least-privilege permissions.
  • Expose only required ports.
  • Configure HTTPS.
  • Restrict database access to the internal Docker network.

πŸ›‘οΈ Docker Scout

Docker Scout can be used to identify vulnerabilities in container images.

Example:

docker scout quickview

You can also inspect an image:

docker scout cves <image-name>

The goal is to identify vulnerable packages and update the relevant base images/dependencies.


🏭 Multi-Stage Docker Builds

For applications that require a build stage, multi-stage Dockerfiles separate build dependencies from the final runtime image.

Concept:

BUILD STAGE
-----------
Install build tools
Install dependencies
Build application
       |
       v
RUNTIME STAGE
-------------
Copy only required output
Run application

Benefits:

  • Smaller images
  • Fewer unnecessary packages
  • Reduced attack surface
  • Faster deployments

πŸ“¦ .dockerignore

.dockerignore prevents unnecessary files from being sent to Docker during image builds.

Typical entries:

.git
.gitignore
.env
__pycache__
*.pyc
venv
node_modules
README.md

This can improve build performance and prevent sensitive/unnecessary files from entering the build context.


🎯 DevOps Concepts Demonstrated

This project is useful as a DevOps learning project because it demonstrates:

Containerization

Application β†’ Docker Image β†’ Container

Orchestration

Docker Compose
      ↓
Django + MySQL + Nginx

Networking

django_cont β†’ db_cont:3306

Reverse Proxy

Client β†’ Nginx β†’ Django

Persistent Storage

MySQL Container β†’ Docker Volume

Service Health

MySQL β†’ Healthcheck β†’ Django

Environment Configuration

.env β†’ Docker Compose β†’ Container

Image Security

Docker Image β†’ Docker Scout β†’ Vulnerability Analysis

🧠 What I Learned From This Project

After completing this project, you should be able to explain:

  • What Docker is
  • Why containers are useful
  • Difference between image and container
  • What Docker Compose does
  • How multiple containers communicate
  • How Docker networking works
  • Why service names can be used as hostnames
  • Why databases require persistent volumes
  • Why healthchecks are important
  • What depends_on does
  • Why Nginx is used as a reverse proxy
  • How Django connects to MySQL
  • How environment variables are passed to containers
  • How to inspect container logs
  • How to troubleshoot startup failures
  • How to expose container ports
  • How to rebuild and restart services
  • How to perform Django migrations inside a container
  • How container image vulnerabilities can be scanned

πŸ’Ό Interview Explanation

If an interviewer asks:

"Explain your Docker project."

You can answer:

"I created a multi-container Django Notes Application using Docker and Docker Compose. The application uses Django as the backend, MySQL for persistent data storage, and Nginx as a reverse proxy. Docker Compose manages the complete application stack, including networking, volumes, environment variables, service dependencies, and healthchecks. Django connects to MySQL through the Docker network using the database container name as the hostname. I also implemented database persistence using Docker volumes and used healthchecks to prevent Django from starting before MySQL was ready. Nginx exposes the application through port 80 and forwards requests to the Django service."


🧩 Project Flow Summary

                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚       Browser        β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                         HTTP :80
                            β”‚
                            β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚        Nginx         β”‚
                 β”‚   Reverse Proxy      β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                         :8000
                            β”‚
                            β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚       Django         β”‚
                 β”‚       Gunicorn       β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                         :3306
                            β”‚
                            β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚        MySQL         β”‚
                 β”‚      test_db         β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚    Docker Volume     β”‚
                 β”‚ Persistent DB Data   β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“‹ Quick Command Cheat Sheet

# Build and start
docker compose up -d --build

# Check containers
docker compose ps

# View logs
docker compose logs -f

# Django logs
docker logs -f django_cont

# MySQL logs
docker logs -f db_cont

# Nginx logs
docker logs -f nginx_cont

# Enter Django container
docker exec -it django_cont sh

# Run migrations
docker exec -it django_cont python manage.py migrate

# Connect to MySQL
docker exec -it db_cont mysql -uroot -proot

# Stop
docker compose down

# Rebuild
docker compose up -d --build

# Remove volumes - USE CAREFULLY
docker compose down -v

🌐 Application URLs

When running locally:

Application through Nginx:
http://localhost

Django direct:
http://localhost:8000

MySQL:
localhost:3306

The recommended browser URL is:

http://localhost

because it represents the intended reverse-proxy architecture.


πŸ“Œ Project Checklist

Before considering the deployment successful, verify:

[ ] Docker installed
[ ] Docker Compose available
[ ] Repository cloned
[ ] .env configured
[ ] Dockerfile available
[ ] docker-compose.yml available
[ ] Nginx configuration available
[ ] Images built successfully
[ ] MySQL container running
[ ] MySQL container healthy
[ ] Django container running
[ ] Django container healthy
[ ] Nginx container running
[ ] Database migrations completed
[ ] Database volume configured
[ ] http://localhost works
[ ] Django logs show no critical errors

πŸ”§ Troubleshooting Flow

When the application does not work, troubleshoot in this order:

1. Check Docker
       ↓
docker --version

2. Check containers
       ↓
docker compose ps

3. Check MySQL
       ↓
docker logs db_cont

4. Check Django
       ↓
docker logs django_cont

5. Check Nginx
       ↓
docker logs nginx_cont

6. Test Django directly
       ↓
curl.exe http://localhost:8000

7. Test Nginx
       ↓
curl.exe http://localhost

8. Check database
       ↓
docker exec -it db_cont mysql -uroot -proot

This approach helps identify whether the problem is with the database, backend, reverse proxy, networking, or application configuration.


πŸ“ˆ Future Improvements

Possible next steps for this project:

  • Add HTTPS with SSL/TLS
  • Use a non-root MySQL application user
  • Add Redis
  • Add Celery for background jobs
  • Add CI/CD with GitHub Actions or Jenkins
  • Push Docker images to Docker Hub/Amazon ECR
  • Deploy to AWS EC2/ECS
  • Add Prometheus and Grafana monitoring
  • Add centralized logging
  • Add automated tests
  • Add image vulnerability scanning to CI/CD
  • Use Docker secrets or a cloud secrets manager
  • Add Kubernetes deployment manifests
  • Add production-ready Gunicorn/Nginx configuration

πŸ“š Learning Resources

This project follows concepts covered in a Docker-focused DevOps learning path, including:

  • Docker fundamentals
  • Docker commands
  • Dockerfiles
  • Docker networking
  • Docker volumes
  • Docker Compose
  • Healthchecks
  • Multi-stage builds
  • Nginx reverse proxy
  • Application containerization
  • Database containers
  • Docker image security
  • Docker Scout

The source material referenced for this project is the Docker In One Shot learning guide by TrainWithShubham.


⭐ Why This Is a Good DevOps Project

This project goes beyond simply running:

docker run

It demonstrates a realistic application architecture:

Application
    +
Database
    +
Reverse Proxy
    +
Container Networking
    +
Persistent Storage
    +
Healthchecks
    +
Environment Configuration
    +
Security Scanning

That makes it a useful portfolio project for demonstrating practical Docker and DevOps fundamentals.


πŸŽ₯ Reference Video

This project is based on the following tutorial by Train with Shubham:

▢️ Dockerizing a Django Application
https://youtu.be/9bSbNNH4Nqw

Creator: Train with Shubham




## πŸ”— Connect With Me

πŸ’Ό **LinkedIn:**  
https://www.linkedin.com/in/hritikranjan1/

🌐 **Website:**  
https://hritikranjan.in

πŸ“ **DevOps Blogs:**  
https://blogs.hritikranjan.in

πŸ’» **GitHub:**  
https://github.com/hritikranjan1

---


<p align="center">
  πŸš€ <b>Built with Docker β€’ Django β€’ MySQL β€’ Nginx β€’ Jenkins</b> πŸš€
</p>

<p align="center">
  ⭐ If you found this project useful, please consider giving the repository a Star!
</p>

About

A Dockerized Django Notes Application demonstrating Docker, Docker Compose, MySQL, Nginx, Jenkins CI/CD, container networking, persistent storage, healthchecks, and environment-based configuration.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages