- Published on
Step by step migration of django cookiecutter postgres to mysql 8+
- Authors
- Name
- Karan Kumar
- @scripter_x
 
 
"Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly."
So, you recently discovered django-cookiecutter and fell in love with a rather opinionated workflow on how files and services are organized but soon you release that django-cookiecutter does not have support for MySQL databases!
There have been some open issues [1] [2] in their repository but they don't provide an out of the box solution to support MySQL.
Prerequisites
I will assume that you already have installed cookiecutter and have run the below command to initialize your project.
$ cookiecutter https://github.com/pydanny/cookiecutter-django
After the project is bootstrapped, you'd be provided with local.yml file to run your project with docker-compose. We are going to
make some changes into the local.yml.
- Replace the highlighted blocks with the below code snippet.
# local.yml
version: '3'
services:
  ...
  django:
    ...
    depends_on:
      - postgres
    ...
  postgres:
    build:
      context: .
      dockerfile: ./compose/production/postgres/Dockerfile
    image: my_awesome_project_production_postgres
    container_name: postgres
    volumes:
      - local_postgres_data:/var/lib/postgresql/data:Z
      - local_postgres_data_backups:/backups:z
    env_file:
      - ./.envs/.local/.postgres
  ...
version: '3'
services:
  ...
  django:
    ...
    depends_on:
      - mysql
    ...
  mysql:
      image: mysql:8.0
      command: --default-authentication-plugin=mysql_native_password --mysqlx=0
      container_name: my_awesome_project_local_mysql
      volumes:
        - "./db:/var/lib/mysql"
      ports:
        - '3306:3306'
      env_file:
        - ./.envs/.local/.mysql
  ...
- Create a new file at ./.envs/.local/.mysqland paste the following environment variables
# MYSQL
MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_DATABASE=<name-of-your-database>
MYSQL_USER=<name-of-your-mysql-user>
MYSQL_PASSWORD=<some-random-password>
MYSQL_ROOT_PASSWORD=<some-root-random-password>
DATABASE_URL=mysql://<name-of-your-mysql-user>:<some-random-password>@mysql:3306/<name-of-your-database>
- Edit the file located in ./compose/local/django/Dockerfileand add the highlighted line
# ./compose/local/django/Dockerfile
FROM python:3.8-slim-buster
...
RUN apt-get update \
  # dependencies for building Python packages
  && apt-get install -y build-essential \
  # psycopg2 dependencies
  && apt-get install -y libpq-dev \
  # install mysql client
  && apt-get install -y default-libmysqlclient-dev \
  # Translations dependencies
  && apt-get install -y gettext \
  # cleaning up unused files
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && rm -rf /var/lib/apt/lists/*
...
COPY ./compose/production/django/entrypoint /entrypoint
...
ENTRYPOINT ["/entrypoint"]
- 
If you have other docker services that uses django, for example docsservice inDockerFile. Edit theDockerfileto install mysql libraries into those container services too.
- 
replace the content of ./compose/production/django/entrypoint(why production? because ofentrypointmentioned in./compose/local/django/Dockerfile) with below code snippet to make your django container aware when your database is ready for connection
# ./compose/production/django/entrypoint
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
export DATABASE_URL="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}"
echo $DATABASE_URL
mysql_ready() {
python << END
import sys
import mysql.connector
try:
    mysql.connector.connect(
      host="${MYSQL_HOST}",
      user="${MYSQL_USER}",
      password="${MYSQL_PASSWORD}",
    )
except Exception as e:
    print('Exception at entrypoint file', e)
    sys.exit(-1)
sys.exit(0)
END
}
until mysql_ready; do
  >&2 echo 'Waiting for MySQL to become available...'
  sleep 1
done
>&2 echo 'Mysql is available'
exec "$@"
- Add the requirement in pip's requirement file ./requirements/base.txt
...
mysql-connector-python==8.0.22
mysqlclient==2.0.1
...
- Run the docker-compose
At this point of time, your project should be able to run below commands successfully
$ docker-compose -f local.yml build
$ docker-compose -f local.yml up
##Changes for production.yml
Follow the similar approach to edit the required files to setup your production.yml to work for mysql container service.