- 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/.mysql
and 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/Dockerfile
and 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
docs
service inDockerFile
. Edit theDockerfile
to install mysql libraries into those container services too. -
replace the content of
./compose/production/django/entrypoint
(why production? because ofentrypoint
mentioned 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.