My Journey with Docker: Containerizing a Django Notes App
Introduction
Learning Docker has been an exciting journey, and I wanted to apply it to a real-world project. I followed Londhe Shubham’s YouTube channel, which helped me understand containerization and its role in DevOps. To solidify my learning, I cloned a Django-based Notes App from GitHub and focused on containerizing it using Docker and Docker Compose.
In this blog, I’ll walk you through how I Dockerized the application and the challenges I faced.
Technologies Used
For this project, I used the following technologies:
Backend: Django, Django REST Framework (Cloned from GitHub)
Database: MySQL
Deployment: Docker, Docker Compose, Nginx
Dockerizing the App
1. Writing the Dockerfile
To containerize the Django application, I created a Dockerfile
that:
Uses a Python base image
Copies application files into the container
Installs dependencies
Runs the Django app with Gunicorn using the following Dockerfile:
# Use official Python image as base
FROM python:3.9
# Set the working directory
WORKDIR /app
# Copy application files
COPY requirements.txt /app/backend
# Install dependencies
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 the application port
EXPOSE 8000
# Run Django with Gunicorn
#RUN python manage.py migrate
#RUN python manage.py makemigrations
2. Setting up Docker Compose
I used Docker Compose to manage multiple services. Below is a breakdown:
version: "3.8"
services:
nginx:
build: ./nginx
image: nginx
container_name: nginx_cont
ports:
- "80:80"
restart: always
depends_on:
- django
networks:
- notes-app
db:
image: mysql
container_name: "db_cont"
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
volumes:
- ./mysql-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot"]
interval: 10s
timeout: 5s
retries: 5
start_period: 60s
networks:
- notes-app
django:
build:
context: .
container_name: "django_cont"
command: sh -c "python manage.py migrate --no-input && gunicorn notesapp.wsgi --bind 0.0.0.0:8000"
ports:
- "8000:8000"
env_file:
- ".env"
restart: always
depends_on:
- db
networks:
- notes-app
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/admin || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 60s
networks:
notes-app:
This setup ensures that:
Django runs inside a container and connects to MySQL.
MySQL data is persisted using Docker volumes.
Nginx acts as a reverse proxy for the Django app.
3. Managing Environment Variables
I stored sensitive database credentials in a .env
file:
DB_NAME=test_db
DB_USER=root
DB_PASSWORD=root
DB_PORT=3306
DB_HOST=db_cont
Running the App with Docker
To spin up the entire stack, I used:
docker-compose up -d
This command launches all services in the background, making the application accessible via Nginx.
Challenges Faced & Solutions
Database Connection Issues
- Solution: Used Docker networks to ensure MySQL and Django containers could communicate.
Docker Volumes for Data Persistence
- Solution: Mounted a volume for MySQL data to avoid data loss when restarting containers.
Django Migrations in Containers
- Solution: Added
python
manage.py
migrate
to the startup command indocker-compose.yml
.
- Solution: Added
Conclusion & Next Steps
This project helped me understand how to containerize an existing web application with Docker. Next, I plan to work on another 3-tier Docker project to deepen my understanding of containerized applications. After that, I'll start exploring Kubernetes and CI/CD integration.
If you’re also learning Docker, I highly recommend applying it to a project like this. Feel free to check out the original repo and try containerizing it yourself!
What’s next on your DevOps learning journey? Let’s connect and discuss!