How to Use MySQL with Django in a Dockerized Environment

Table of Contents

Introduction
Project Structure
Setting Up Django and MySQL with Docker
Configure Django to Use MySQL
Running the Project
Creating and Applying Migrations
Conclusion


Introduction

Django supports several relational databases out of the box, including MySQL. While SQLite is great for simple or local development, MySQL is often used in production due to its performance, scalability, and wide adoption.

In this guide, you'll learn how to set up a Django project to use MySQL, containerized using Docker and Docker Compose. This setup ensures consistent development environments and makes it easier to deploy or collaborate on projects.


Project Structure

Here’s what the folder structure will look like:

django-mysql-docker/
├── app/
│   ├── manage.py
│   ├── myproject/
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   └── myapp/
│       ├── models.py
│       └── views.py
├── Dockerfile
├── docker-compose.yml
└── requirements.txt

Setting Up Django and MySQL with Docker

Dockerfile for Django

Create a Dockerfile in the project root:

# Use the official Python runtime image
FROM python:3.13

# Create the app directory
RUN mkdir /app

# Set the working directory inside the container
WORKDIR /app

# Set environment variables 
# Prevents Python from writing pyc files to disk
ENV PYTHONDONTWRITEBYTECODE=1
#Prevents Python from buffering stdout and stderr
ENV PYTHONUNBUFFERED=1

# Install system dependencies (gcc, mysql-client for MySQL database connection, curl for Node.js)
RUN apt update && apt install -y \
    gcc \
    default-libmysqlclient-dev \
    && rm -rf /var/lib/apt/lists/*

# Upgrade pip
RUN pip install --upgrade pip 

# Copy the Django project and install dependencies
COPY requirements.prod.txt  /app/

# run this command to install all dependencies 
RUN pip install --no-cache-dir -r requirements.prod.txt

# Copy the Django project to the container
COPY . /app/

# Expose the Django port
EXPOSE 8000

# Start the application using Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "blogproject.wsgi:application"]

docker-compose.yml

Create a docker-compose.yml file:

services:
  django-app:
    build:
      context: .
      dockerfile: Dockerfile.prod
    container_name: django-app
    restart: always
    volumes:
      - ./staticfiles:/app/staticfiles
    ports:
      - "8000:8000"
    environment:
      - DB_HOST=db # Reference environment variable from .env file
      - DB_NAME=${DB_NAME}
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
      - SECRET_KEY=${SECRET_KEY}
      - DEBUG=${DEBUG}
      - DJANGO_ALLOWED_HOSTS=${DJANGO_ALLOWED_HOSTS}
      - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS}
    depends_on:
      - db # Make sure the database service starts first
    env_file:
      - .env
    command: >
      sh -c "python manage.py wait_for_db &&
             python manage.py migrate &&
             python manage.py collectstatic --noinput &&
             gunicorn --bind 0.0.0.0:8000 blogproject.wsgi:application"
  db:
    image: mysql:8.0.41
    volumes:
      - mysql_db:/var/lib/mysql # Persist the database data
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} # Use the root password from .env file
      - MYSQL_DATABASE=${DB_NAME} # The database name from .env file
    ports:
      - "3306:3306" # MySQL default port
    env_file:
      - .env

volumes:
  mysql_db: # Named volume for MySQL data persistence

requirements.txt

Your requirements.txt should include Django and the MySQL client:

django>=5.1.7,<5.2
mysqlclient>=2.2.7,<2.3
gunicorn==23.0.0

Configure Django to Use MySQL

In your app/myproject/settings.py, update the DATABASES setting to use MySQL:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.getenv('DB_NAME'),           # Name of your MySQL database
        'USER': os.getenv('DB_USER'),           # MySQL username
        'PASSWORD': os.getenv('DB_PASSWORD'),   # MySQL password
        'HOST': os.getenv('DB_HOST'),           # MySQL service name 
        'PORT': '3306',                         # MySQL default port
    }
}

Make sure HOST is set to the name of the database service (db), which is defined in docker-compose.yml.


Running the Project

Build and start the containers:

docker compose up -d --build

Now your Django app should be running at:
http://localhost:8000

And MySQL will be running inside its own container, available on port 3306 if needed.

Stop the container*

docker compose down

Conclusion

Using Docker to run Django with a MySQL backend is a practical way to ensure consistent environments across development and deployment. With just a few configuration files, you can spin up a portable environment that includes both your web application and database.