π³ Dockerizing a Django Notes Application: Complete DevOps Project with Docker Compose, MySQL & Nginx
If you are learning Docker, DevOps, Cloud, or CI/CD, one of the best ways to understand Docker is to work with a real application instead of only learning individual commands.

In this project, I containerized a Django Notes Application and deployed it using Docker and Docker Compose.
The project demonstrates several important DevOps concepts:
π³ Docker Containerization
βοΈ Docker Compose
π Django
ποΈ MySQL
π Nginx Reverse Proxy
π Docker Networking
πΎ Docker Volumes
β€οΈ Healthchecks
π Environment Variables
π‘οΈ Docker Scout
π Application Deployment
π Container Troubleshooting
The final architecture looks like this:
USER / BROWSER
|
| HTTP :80
β
+--------------+
| NGINX |
| Reverse Proxy|
+--------------+
|
| HTTP :8000
β
+--------------+
| DJANGO |
| Backend |
+--------------+
|
| MySQL :3306
β
+--------------+
| MYSQL |
| Database |
+--------------+
|
β
DOCKER VOLUME
This project helped me understand how multiple containers can work together as one application.
π Table of Contents
π What Are We Building?
We are taking a Django Notes Application and converting it into a multi-container Docker application.
Instead of installing everything directly on the host machine:
Windows/Linux
|
+-- Python
+-- Django
+-- MySQL
+-- Nginx
+-- Dependencies
we run the application using separate containers:
Docker
|
+-- Django Container
|
+-- MySQL Container
|
+-- Nginx Container
Each component has its own responsibility.
This is one of the fundamental ideas behind containerized application architecture.
π Project Overview
The project uses:
Django for application/backend logic
MySQL for persistent application data
Nginx as a reverse proxy
Docker for containerization
Docker Compose for multi-container orchestration
.envfor configurationDocker Volumes for persistent database storage
Healthchecks to verify service readiness
The project follows a simple three-tier architecture:
User
|
β
Nginx
|
β
Django
|
β
MySQL
|
β
Docker Volume
The project structure and components are based on the uploaded project documentation.
π€ Why Dockerize a Django Application?
Without Docker, developers may need to manually install:
Python
Django
MySQL
Nginx
Python packages
System dependencies
This can create the classic problem:
"It works on my machine."
For example:
Developer Machine
|
| Different Python version
| Different packages
| Different database configuration
β
Application works differently
Docker solves much of this by packaging the application and its environment into reproducible containers.
The same Docker image can be used across:
Development
β
Testing
β
Staging
β
Production
ποΈ Architecture
Our application contains three primary services.
1οΈβ£ Django Container
Django is responsible for the application logic.
It:
Handles requests
Processes application logic
Communicates with MySQL
Runs migrations
Runs through Gunicorn
The internal application port is:
8000
2οΈβ£ MySQL Container
MySQL stores application data.
It runs on:
3306
The database configuration can look like:
DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_HOST=db_cont
DB_PORT=3306
An important Docker concept here is:
db_cont
is the hostname used by Django to reach the MySQL container.
It is not the MySQL username.
The project documentation specifically uses db_cont as the database hostname.
3οΈβ£ Nginx Container
Nginx acts as the reverse proxy.
It accepts traffic on:
Port 80
and forwards requests to Django:
Nginx :80
|
β
Django :8000
So users don't need to directly access Django.
π§° Technology Stack
| Technology | Purpose |
|---|---|
| Docker | Containerization |
| Docker Compose | Multi-container orchestration |
| Django | Backend/Application |
| Python | Programming language |
| MySQL | Database |
| Nginx | Reverse Proxy |
| Gunicorn | Django application server |
| Docker Network | Container communication |
| Docker Volume | Persistent storage |
.env |
Environment configuration |
| Docker Scout | Vulnerability scanning |
π Project Structure
A typical project structure looks like this:
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 directory names can vary depending on the repository implementation.
π How the Application Works
When a user opens:
http://localhost
the request follows this path:
Browser
|
β
Nginx :80
|
β
Django/Gunicorn :8000
|
β
Django processes request
|
β
MySQL :3306
|
β
Database returns data
|
β
Django generates response
|
β
Nginx
|
β
Browser
This separation makes the application easier to maintain, troubleshoot and scale.
π³ Dockerfile
A Dockerfile tells Docker how to build the application image.
The basic process is:
Base Python Image
β
Install System Dependencies
β
Install Python Dependencies
β
Copy Application
β
Configure Application
β
Start Django/Gunicorn
A Dockerfile typically contains instructions such as:
FROM python:3.9
WORKDIR /app/backend
COPY requirements.txt /app/backend
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y gcc default-libmysqlclient-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*
# Install app dependencies
RUN pip install mysqlclient
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app/backend
EXPOSE 8000
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
#RUN python manage.py migrate
#RUN python manage.py makemigrations
The exact Dockerfile should follow the application's actual dependency and startup requirements.
The important DevOps concept is that the Dockerfile turns the application source code into a reproducible Docker image.
π Environment Variables
Hardcoding configuration inside application code is not a good practice.
Instead, configuration can be stored in:
.env
For example:
DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_PORT=3306
DB_HOST=db_cont
MySQL can use compatible variables such as:
MYSQL_DATABASE=test_db
MYSQL_ROOT_PASSWORD=root
What does each variable mean?
| Variable | Meaning |
|---|---|
DB_NAME |
Database name |
DB_USER |
Database username |
DB_PASSWORD |
Database password |
DB_HOST |
Database hostname |
DB_PORT |
Database port |
The .env file keeps configuration separate from application source code.
β οΈ Important Security Rule
Never commit real credentials to GitHub.
Add:
.env
to:
.env
For production, use a proper secrets-management solution.
ποΈ MySQL Database
The database runs inside its own Docker container.
Example:
MySQL Container
|
β
test_db
Django connects to MySQL through the Docker network.
Example:
DB_HOST=db_cont
DB_PORT=3306
Notice that we don't use:
localhost
for the Django-to-MySQL connection.
Why?
Because inside the Django container:
localhost
means:
Django container itself
It does not mean the MySQL container.
Instead, Docker provides service/container-name based communication:
Django Container
|
β
db_cont:3306
|
β
MySQL Container
π Docker Networking
Docker Compose creates a network that allows containers to communicate.
For example:
django_cont
|
| Docker Network
|
β
db_cont:3306
This means Django can connect to MySQL using:
db_cont
rather than a hardcoded IP address.
This is much more reliable because container IP addresses can change.
Docker's internal DNS resolves the container/service name.
πΎ Docker Volumes
One of the most important concepts in this project is persistent storage.
Containers are temporary.
Imagine:
MySQL Container
|
β
Database Data
If the container is deleted without persistent storage:
Container deleted
β
Potential data loss
A Docker volume solves this problem.
MySQL Container
|
β
Docker Volume
|
β
Persistent Data
Example:
volumes:
mysql_data:
and:
services:
db:
volumes:
- mysql_data:/var/lib/mysql
Now:
Container removed
β
Volume remains
β
Database data remains
This is extremely important for databases.
βοΈ Docker Compose
Docker Compose is the central part of this project.
Instead of manually running several commands:
docker run ...
docker run ...
docker run ...
we define the complete architecture inside:
docker-compose.yml
Compose can define:
Services
Images
Builds
Ports
Environment variables
Networks
Volumes
Dependencies
Healthchecks
Restart policies
Conceptually:
version: "3.8"
services:
nginx:
build: ./nginx
image: nginx
container_name: "nginx_cont"
ports:
- "80:80"
restart: always
depends_on:
- django_app
networks:
- notes-app-nw
django_app:
build:
context: .
image: django_app
container_name: "django_cont"
ports:
- "8000:8000"
command: sh -c "python manage.py migrate --noinput && gunicorn notesapp.wsgi --bind 0.0.0.0:8000"
env_file:
- ".env"
depends_on:
- db
restart: always
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/admin || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- notes-app-nw
db:
image: mysql
container_name: "db_cont"
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=test_db
volumes:
- ./data/mysql/db:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot"]
interval: 10s
timeout: 5s
retries: 5
start_period: 60s
networks:
- notes-app-nw
networks:
notes-app-nw:
The project documentation identifies Compose as the blueprint for the complete application stack.
β€οΈ Healthchecks
A common problem with multi-container applications is startup order.
Suppose:
MySQL starts
β
Django starts immediately
β
Django tries connecting to MySQL
β
MySQL is still initializing
β
Connection fails
This can cause Django to restart.
A healthcheck allows Docker to determine whether MySQL is actually ready.
Example:
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 10
The flow becomes:
MySQL starts
β
Healthcheck
β
MySQL ready
β
Healthy
β
Django starts/connects
This is different from simply checking whether the MySQL container is running.
A container can be running but its application may not yet be ready.
That's why healthchecks are useful.
π Nginx Reverse Proxy
Nginx is the public entry point of our application.
Without Nginx:
User
β
Django
With Nginx:
User
β
Nginx
β
Django
Nginx listens on:
80
and forwards traffic to:
Django :8000
Why use Nginx?
Nginx can provide:
Reverse proxy
Static file serving
Centralized traffic handling
SSL/TLS termination
Access control
Caching
Better production architecture
Easier future scaling
The project therefore exposes the application through Nginx instead of making Django the primary public entry point.
π» Setup & Installation
Before starting the project, install:
Docker Desktop
Git
VS Code or another code editor
Check Docker:
docker --version
Check Docker Compose:
docker compose version
Check Git:
git --version
π₯ Clone the Project
Clone the repository:
git clone https://github.com/hritikranjan1/django-notes-app.git
Move into the project directory:
cd django-notes-app
π Configure Environment Variables
Create:
.env
Example:
DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_PORT=3306
DB_HOST=db_cont
The MySQL service should use compatible configuration:
MYSQL_DATABASE=test_db
MYSQL_ROOT_PASSWORD=root
Make sure both Django and MySQL use matching database configuration.
For learning purposes, simple values can be used.
For production, use:
Strong passwords
Dedicated database users
Secret managers
Environment-specific configuration
ποΈ Build and Start Containers
The recommended modern Docker Compose command is:
docker compose up -d --build
Let's understand what happens.
docker compose
Runs Docker Compose.
up
Creates and starts the services.
-d
Runs containers in detached mode.
--build
Builds the application image before starting.
So:
docker compose up -d --build
will:
Build Images
β
Create Network
β
Create Volume
β
Create Containers
β
Start MySQL
β
Check Health
β
Start Django
β
Start Nginx
π Check Running Containers
Run:
docker ps
You should see containers similar to:
db_cont
django_cont
nginx_cont
You can also use:
docker compose ps
Example:
NAME STATUS
db_cont Up (healthy)
django_cont Up
nginx_cont Up
The project documentation uses these container names for the three-service architecture.
π Access the Application
The recommended URL is:
http://localhost
because traffic goes through Nginx.
If Django port 8000 is exposed, you may also test:
http://localhost:8000
But this bypasses Nginx.
The architecture we want users to follow is:
Browser
β
localhost:80
β
Nginx
β
Django:8000
π§ͺ Test Django
On Windows PowerShell:
curl.exe http://localhost:8000
A successful application should return an HTTP success response such as:
HTTP/1.1 200 OK
π Test Nginx
Run:
curl.exe http://localhost
Then open:
http://localhost
in your browser.
If the application loads, the basic architecture is working.
ποΈ Connect to MySQL
If the MySQL container is:
db_cont
connect using:
docker exec -it db_cont mysql -uroot -proot
Once inside MySQL:
SHOW DATABASES;
Select the database:
USE test_db;
Check tables:
SHOW TABLES;
Exit:
exit;
This is useful when debugging database-related problems.
π Run Django Migrations
Django migrations create and update the database schema required by the application.
Enter the Django container:
docker exec -it django_cont sh
Then:
python manage.py migrate
You can check migration status:
python manage.py showmigrations
Exit:
exit
You can also run migration directly:
docker exec -it django_cont python manage.py migrate
The project documentation specifically uses migrations to initialize the application's database tables.
π Logs and Troubleshooting
Logs are one of the most important tools when working with Docker.
View all Compose logs
docker compose logs
Follow logs continuously:
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
Use:
docker compose ps
or:
docker ps
For deeper investigation:
docker inspect django_cont
This can show:
Network configuration
Environment
Mounts
Container settings
IP information
Runtime configuration
π Stop the Project
To stop the application:
docker compose down
This removes the containers and Compose network.
Named volumes are normally preserved.
βΆοΈ Start the Project Again
After stopping:
docker compose up -d
If code or Docker configuration changed:
docker compose up -d --build
π§Ή Remove Containers and Volumes
To remove containers and volumes:
docker compose down -v
β οΈ Be careful.
Removing the MySQL volume can remove persistent database data.
Use:
docker compose down -v
only when you intentionally want to delete the stored database data.
π Rebuild From Scratch
If you need a clean image rebuild:
docker compose down
Then:
docker compose build --no-cache
Then:
docker compose up -d
Avoid using:
docker compose down -v
unless you intentionally want to delete the database volume.
π§° Useful Docker Commands
List running containers
docker ps
List 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
Enter Django container
docker exec -it django_cont sh
Restart Django
docker compose restart django
Stop Django
docker compose stop django
Start Django
docker compose start django
π Common Problems
β Problem 1: Django Cannot Connect to MySQL
You may see:
django.db.utils.OperationalError:
Can't connect to server on 'db_cont'
Possible reason
MySQL may still be initializing.
Check:
docker compose ps
Then:
docker logs db_cont
Look for:
ready for connections
If MySQL is not ready, Django may fail to connect.
Healthchecks and dependency configuration can help solve this startup timing issue.
β Problem 2: Django Container Keeps Restarting
Check:
docker logs django_cont
Possible causes:
Database unavailable
Incorrect
.envMissing Python package
Migration failure
Incorrect Django settings
Incorrect startup command
Always start troubleshooting with the logs.
β Problem 3: Nginx Is Running But Application Does Not Open
First check:
docker logs nginx_cont
Then:
docker logs django_cont
Test Django directly:
curl.exe http://localhost:8000
If:
localhost:8000
works but:
localhost
does not work, investigate the Nginx configuration.
β Problem 4: Port Already in Use
You may see:
port is already allocated
On Windows, check port 80:
netstat -ano | findstr :80
Check port 8000:
netstat -ano | findstr :8000
This helps identify whether another process is already using the port.
β Problem 5: Database Exists But Tables Are Missing
Run:
docker exec -it django_cont python manage.py migrate
Then connect to MySQL:
docker exec -it db_cont mysql -uroot -proot
Run:
USE test_db;
SHOW TABLES;
If migrations were successful, the required Django tables should be present.
β Problem 6: .env Changes Are Not Reflected
After changing environment variables, recreate the services:
docker compose down
Then:
docker compose up -d --build
If required:
docker compose up -d --force-recreate
This ensures the containers are recreated with the updated configuration.
π‘οΈ Docker Scout
Security is an important part of DevOps.
Docker Scout can be used to inspect Docker images for vulnerabilities.
Run:
docker scout quickview
You can also scan an image:
docker scout cves <image-name>
The goal is to identify vulnerable packages and update the relevant base images or dependencies.
A useful DevSecOps flow is:
Dockerfile
β
Build Image
β
Docker Scout
β
Vulnerability Analysis
β
Fix Vulnerabilities
β
Build Again
π Multi-Stage Docker Builds
For larger applications, multi-stage builds can reduce the final image size.
The basic concept is:
BUILD STAGE
-----------
Install build tools
Install dependencies
Build application
|
β
RUNTIME STAGE
-------------
Copy required output
Run application
Benefits include:
Smaller images
Fewer unnecessary packages
Reduced attack surface
Faster deployments
The project documentation lists multi-stage builds as a potential optimization concept.
π¦ .dockerignore
A .dockerignore file prevents unnecessary files from being sent to Docker during the build.
Example:
.git
.gitignore
.env
__pycache__
*.pyc
venv
node_modules
README.md
Why is this useful?
Because we don't want unnecessary files inside our Docker build context.
It can:
Reduce build context size
Improve build performance
Avoid copying unnecessary files
Help prevent sensitive files from entering the build context
The project README includes .dockerignore as part of the recommended project setup.
π Security Best Practices
For learning purposes, simple credentials such as:
DB_USER=root
DB_PASSWORD=root
may be used.
But never use this approach for a real production system.
For production:
1. Don't use MySQL root
Create a dedicated application user.
2. Use strong passwords
Avoid:
root
password
123456
3. Don't commit .env
Add:
.env
to:
.gitignore
4. Use secrets management
Examples include cloud secret-management solutions.
5. Scan Docker images
Use Docker Scout or another image scanning solution.
6. Keep images updated
Use maintained base images and update dependencies.
7. Follow least privilege
Give applications only the permissions they actually need.
8. Expose only required ports
Avoid unnecessarily exposing the database publicly.
9. Use HTTPS
Production applications should use SSL/TLS.
10. Keep the database internal
The database should generally communicate through the internal Docker network instead of being directly exposed to the internet.
These security recommendations are also included in the project's documentation.
π― DevOps Concepts Demonstrated
This project is more than just a Django application.
It demonstrates several real DevOps concepts.
π³ Containerization
Application
β
Docker Image
β
Container
βοΈ Orchestration
Docker Compose
β
Django + MySQL + Nginx
π Networking
django_cont
β
Docker Network
β
db_cont:3306
π Reverse Proxy
Client
β
Nginx
β
Django
πΎ Persistent Storage
MySQL Container
β
Docker Volume
β
Persistent Database Data
β€οΈ Healthchecks
MySQL
β
Healthcheck
β
Healthy
β
Django
π Configuration
.env
β
Docker Compose
β
Container
π‘οΈ Image Security
Docker Image
β
Docker Scout
β
Vulnerability Analysis
The project's documentation explicitly identifies these as the key DevOps concepts demonstrated by the deployment.
π§ What I Learned From This Project
After completing this project, I gained practical understanding of:
What Docker is
Why containers are useful
Difference between Docker image and container
What Docker Compose does
How multiple containers communicate
How Docker networking works
Why service names can act as hostnames
Why databases require persistent storage
Why Docker volumes are important
Why healthchecks matter
What
depends_onis used forWhy 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 ports
How to rebuild containers
How to perform Django migrations inside a container
How to scan container images for vulnerabilities
This turned Docker from a collection of commands into a practical deployment workflow.
πΌ How to Explain This Project in an Interview
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 communicates with MySQL through the Docker network using the database container name as the hostname. I used Docker volumes to persist database data and healthchecks to ensure MySQL is ready before the application depends on it. Nginx acts as the public entry point on port 80 and forwards requests to the Django application running on port 8000."
This explanation covers the major DevOps concepts implemented in the project.
π₯ Important Interview Questions
1. Why did you use Docker Compose?
Because the application contains multiple services.
Instead of manually managing each container, Docker Compose allows us to define and manage the entire stack using one configuration file.
2. Why did you use a Docker volume?
Because database data needs to survive container recreation.
Container
β
Volume
β
Persistent Data
3. Why can't Django use localhost to connect to MySQL?
Because Django and MySQL run in separate containers.
Inside the Django container:
localhost
refers to the Django container itself.
Therefore Django uses:
db_cont:3306
to communicate with MySQL.
4. Why is Nginx used?
Nginx acts as a reverse proxy and provides a single public entry point.
User
β
Nginx
β
Django
5. Why are healthchecks required?
Because a container being started does not always mean the application inside it is ready.
MySQL may need several seconds before accepting connections.
Healthchecks help verify readiness.
6. What happens when you run docker compose down?
It stops and removes the Compose-managed containers and network.
Named volumes are normally preserved.
7. What happens with docker compose down -v?
It also removes the associated volumes.
For a database, this can mean losing persistent data.
8. How do you troubleshoot a container?
First:
docker compose ps
Then check logs:
docker logs <container>
For example:
docker logs django_cont
docker logs db_cont
docker logs nginx_cont
π Complete Project Flow
The complete deployment can be visualized as:
βββββββββββββββββββββ
β Browser β
βββββββββββ¬ββββββββββ
β
HTTP :80
β
βΌ
βββββββββββββββββββββ
β Nginx β
β Reverse Proxy β
βββββββββββ¬ββββββββββ
β
:8000
β
βΌ
βββββββββββββββββββββ
β Django β
β Gunicorn β
βββββββββββ¬ββββββββββ
β
:3306
β
βΌ
βββββββββββββββββββββ
β MySQL β
β test_db β
βββββββββββ¬ββββββββββ
β
βΌ
βββββββββββββββββββββ
β Docker Volume β
β Persistent Storageβ
βββββββββββββββββββββ
This is the overall flow implemented by the project.
π Quick Docker Command Cheat Sheet
# Build and start
docker compose up -d --build
# Check containers
docker compose ps
# View all 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 application
docker compose down
# Start application
docker compose up -d
# Rebuild
docker compose up -d --build
# Remove volumes
docker compose down -v
β οΈ Remember: use docker compose down -v carefully because database volumes contain persistent data.
π Application URLs
When running locally:
Application through Nginx
http://localhost
Django direct access
http://localhost:8000
MySQL
localhost:3306
The preferred browser URL is:
http://localhost
because it represents the intended Nginx reverse-proxy architecture.
β Project Success 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
[ ] Nginx container running
[ ] Database migrations completed
[ ] Database volume configured
[ ] http://localhost works
[ ] Django logs show no critical errors
π§ Troubleshooting Flow
When something doesn't work, don't randomly change configurations.
Follow a structured troubleshooting process:
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
β
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 related to:
Database
β
Backend
β
Networking
β
Nginx
β
Application Configuration
π Future Improvements
This project can be extended into a more production-ready DevOps project.
1. Add HTTPS
Configure SSL/TLS for secure communication.
HTTPS
β
Nginx
β
Django
2. Use a Non-Root Database User
Instead of:
root
create a dedicated application user with only the required permissions.
3. Add Redis
Redis can be introduced for:
Caching
Session storage
Background jobs
4. Add Celery
Celery can handle background tasks asynchronously.
Architecture:
Django
β
Celery
β
Redis
5. Add CI/CD
The project can be connected to:
GitHub Actions
Jenkins
Example:
Git Push
β
CI Pipeline
β
Run Tests
β
Build Docker Image
β
Security Scan
β
Push Image
β
Deploy
6. Push Images to a Registry
For example:
Docker Hub
or:
Amazon ECR
7. Deploy to AWS
The application could be deployed using:
AWS EC2
or:
AWS ECS
8. Add Monitoring
Add:
Prometheus
+
Grafana
for monitoring and visualization.
9. Centralized Logging
A production environment should have centralized logging so that application and infrastructure logs can be searched and analyzed.
10. Kubernetes
A natural next step would be converting the Docker Compose architecture into Kubernetes manifests.
For example:
Docker Compose
β
Kubernetes
β
Deployments
Services
ConfigMaps
Secrets
Persistent Volumes
These improvements are listed in the project's documentation as possible next steps.
π What This Project Taught Me About DevOps
The biggest lesson from this project is that Docker is not just about creating containers.
A real application requires several components to work together:
Application
+
Database
+
Networking
+
Persistent Storage
+
Reverse Proxy
+
Healthchecks
+
Configuration
+
Security
Docker Compose allows us to define this complete architecture in a repeatable way.
The result is:
One Application
β
Multiple Containers
β
One Managed Architecture
This is much closer to how modern applications are deployed than simply running a single Docker container.
π Why This Is a Good DevOps Portfolio Project
A basic Docker project might only demonstrate:
docker build
docker run
This project goes much further.
It demonstrates:
π³ Containerization
+
βοΈ Orchestration
+
π Networking
+
πΎ Persistent Storage
+
π Reverse Proxy
+
β€οΈ Healthchecks
+
π Environment Configuration
+
π‘οΈ Security Scanning
That makes it a useful beginner-to-intermediate DevOps portfolio project.
It gives you something practical to discuss during interviews instead of only saying:
"I know Docker."
You can explain:
"I containerized a Django application, connected it to MySQL through a Docker network, persisted database data using volumes, placed Nginx in front of Django as a reverse proxy, configured service healthchecks, managed the entire stack with Docker Compose, and performed container troubleshooting and image security scanning."
That is a much stronger project explanation.
π₯ Reference Tutorial
This project was built while learning from the Docker-focused tutorial by Train with Shubham.
YouTube:
The project documentation also references this tutorial as the learning source.
π» Project Repository
GitHub:
https://github.com/hritikranjan1/django-notes-app.git
You can explore the complete Dockerized Django project, configuration files, Docker setup and documentation there.
π Conclusion
Building this Django Notes Application helped me understand how Docker can be used to deploy a complete multi-container application.
The final architecture contains:
Browser
β
Nginx
β
Django/Gunicorn
β
MySQL
β
Docker Volume
And Docker Compose manages the complete environment.
The most important concepts I learned were:
Docker containerization
Docker images
Docker Compose
Container networking
Environment variables
Docker volumes
Database persistence
Healthchecks
Nginx reverse proxy
Django migrations
Container troubleshooting
Docker image security
This project also provides a strong foundation for moving toward more advanced DevOps technologies such as:
CI/CD
β
AWS
β
Jenkins / GitHub Actions
β
Monitoring
β
Kubernetes
If you are a beginner learning Docker, I highly recommend building a project like this instead of only memorizing Docker commands.
Learn β Build β Break β Troubleshoot β Improve.
That's where the real DevOps learning happens. π
π 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
β If you found this project useful, consider giving the repository a Star!
π Built with Docker β’ Django β’ MySQL β’ Nginx β’ DevOps
Happy Dockering!
π Complete Learning & Career Resources | 2027β2028
A curated collection of learning resources for AI, Data Analytics, Python, Data Engineering, Cybersecurity, Cloud, Networking, Finance, Digital Marketing, Project Management, DevOps and Generative AI.
π Learn Β βΒ π§ͺ Practice Β βΒ π οΈ Build Β βΒ π Share Β βΒ π Grow
π About This Repository
Welcome to the Complete Learning & Career Resources Repository! π
This repository is designed as a centralized learning hub for students, developers, QA engineers, DevOps engineers, cloud learners, cybersecurity enthusiasts, data professionals, project managers, business professionals and anyone interested in continuous learning.
The goal is simple:
Learn β Practice β Build β Document β Share β Grow
Instead of searching for useful resources again and again, this repository brings them together in one place.
π― What You Will Find Here
π€ Artificial Intelligence
π§ Generative AI
π Data Analytics
π Python
βοΈ Data Engineering
βοΈ Cloud Computing
π Computer Networking
π Cybersecurity
βοΈ DevOps
π Project Management
π° Finance
π Digital Marketing
π§© Business Analysis
π Career Development
π Professional Learning
π οΈ Project Ideas
π Learning Roadmaps
π Repository Overview
| Category | Resources |
|---|---|
| π€ AI Courses | 15 |
| π΅ Google Courses | 15 |
| π£ IBM Courses | 10 |
| π₯ Best Courses 2027β2028 | 21 |
| π Learning & Career Resources | 14 |
| π Personal Resources | 4+ |
π Table of Contents
π€ AI Courses
π Explore AI fundamentals, Python, AI infrastructure, Generative AI, AI governance and specialized AI applications.
| # | Course | Link |
|---|---|---|
| 1 | AI For Everyone | Start Course β |
| 2 | AI Python for Beginners | Start Course β |
| 3 | AI Infrastructure and Operations Fundamentals | Start Course β |
| 4 | Generative AI for Human Resources (HR) Professionals | Start Course β |
| 5 | AI Fundamentals | Start Course β |
| 6 | AI for Healthcare | Start Course β |
| 7 | AI Applications in Accounting and Finance | Start Course β |
| 8 | AI Governance and Privacy Professional Certification (AIGP) | Start Course β |
| 9 | Ethics and Governance in the Age of Generative AI | Start Course β |
| 10 | Hands-on quantum error correction with Google Quantum AI | Start Course β |
| 11 | AI-Powered Higher Education | Start Course β |
| 12 | Modern Project Leadership: Agile, AI, and Beyond | Start Course β |
| 13 | AI-Powered Business Analysis: Excel, KPIs & GenAI | Start Course β |
| 14 | AI in Law: Research, Risk, and Legal Drafting | Start Course β |
| 15 | Generative AI for Project Managers | Start Course β |
π΅ Google Courses
π Explore Data Analytics, AI, Cybersecurity, Networking, Cloud, Digital Marketing and Project Management.
| # | Course | Link |
|---|---|---|
| 1 | Foundations: Data, Data, Everywhere | Start Course β |
| 2 | Ask Questions to Make Data-Driven Decisions | Start Course β |
| 3 | Prepare Data for Exploration | Start Course β |
| 4 | Agile Project Management | Start Course β |
| 5 | Project Initiation: Starting a Successful Project | Start Course β |
| 6 | AI Fundamentals | Start Course β |
| 7 | Foundations of Digital Marketing and E-commerce | Start Course β |
| 8 | Play It Safe: Manage Security Risks | Start Course β |
| 9 | The Bits and Bytes of Computer Networking | Start Course β |
| 10 | Analyze Data to Answer Questions | Start Course β |
| 11 | Automate Cybersecurity Tasks with Python | Start Course β |
| 12 | Architecting with Google Compute Engine | Start Course β |
| 13 | AI for Writing and Communicating | Start Course β |
| 14 | From Likes to Leads: Interact with Customers Online | Start Course β |
| 15 | AI for Data Analysis | Start Course β |
π£ IBM Courses
π Explore SQL, Python, Data Analytics, Deep Learning, RAG and Generative AI resources.
| # | Course | Link |
|---|---|---|
| 1 | Databases and SQL for Data Science with Python | Start Course β |
| 2 | RAG and Agentic AI Capstone Project | Start Course β |
| 3 | Excel Basics for Data Analysis | Start Course β |
| 4 | Introduction to Data Analytics | Start Course β |
| 5 | Data Visualization and Dashboards with Excel and Cognos | Start Course β |
| 6 | IBM AI Foundations for Business | Start Course β |
| 7 | AI Capstone Project with Deep Learning | Start Course β |
| 8 | Python Project for Data Engineering | Start Course β |
| 9 | Building Generative AI-Powered Applications with Python | Start Course β |
| 10 | Vector Databases for RAG: An Introduction | Start Course β |
π₯ Best Courses 2027β2028
π― A broader collection covering AI, Data, Python, Finance, Cybersecurity, Marketing, Networking, Management and Data Engineering.
| # | Course | Link |
|---|---|---|
| 1 | AI For Everyone | Start Course β |
| 2 | Foundations: Data, Data, Everywhere | Start Course β |
| 3 | Ask Questions to Make Data-Driven Decisions | Start Course β |
| 4 | Prepare Data for Exploration | Start Course β |
| 5 | Financial Markets | Start Course β |
| 6 | Agile Project Management | Start Course β |
| 7 | Play It Safe: Manage Security Risks | Start Course β |
| 8 | Project Initiation: Starting a Successful Project | Start Course β |
| 9 | AI Fundamentals | Start Course β |
| 10 | Analyze Data to Answer Questions | Start Course β |
| 11 | Foundations of Digital Marketing and E-commerce | Start Course β |
| 12 | The Bits and Bytes of Computer Networking | Start Course β |
| 13 | Sequence Models | Start Course β |
| 14 | Federal Taxation I: Individuals, Employees, and Sole Proprietors | Start Course β |
| 15 | Designing the Organization | Start Course β |
| 16 | Game Theory | Start Course β |
| 17 | Using Python to Access Web Data | Start Course β |
| 18 | Viral Marketing and How to Craft Contagious Content | Start Course β |
| 19 | Python Project for Data Engineering | Start Course β |
| 20 | Value Chain Management | Start Course β |
| 21 | Applying Data Analytics in Finance | Start Course β |
π Learning & Career Resources
π‘ Additional resources for learning, career development, language learning, hosting, education and professional growth.
πΊοΈ Recommended Learning Roadmaps
Choose one roadmap according to your career goal. You don't need to learn everything at once.
π€ AI Roadmap
AI Fundamentals
β
Python Basics
β
Mathematics & Statistics
β
Data Fundamentals
β
Machine Learning
β
Deep Learning
β
Generative AI
β
Prompt Engineering
β
RAG
β
Vector Databases
β
Agentic AI
β
AI Applications
β
Real-World Projects
β
GitHub Portfolio






