Django / MySQL with Docker  – A step by step guide for local development part 2

In part 1 we covered the basic setup of Django in docker. In this part, we are going to add MySQL to this stack.

Ok then lets start.

Note: On Docker for Mac and Docker for Windows, go to http://localhost:8000 on a web browser to see the Django app.
If you are using Docker Machine, then
docker-machine ip MACHINE_VM
returns the Docker host IP address, to which you can append the port (:8000).

To change the port, edit the “docker-compose.yml” file like given below. This would run it on the port 3000 instead of 8000. So to access you need to append the port number 3000 instead of 8000.

version: "3"
services:
  app:
    restart: always
    build: . # Current directory!
    command: "python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "3000:8000"

Let us now add MySQL to this. Edit the compose files as below

version: "3"
services:
  app:
    restart: always
    build: . # Current directory!
    command: "python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "3000:8000"
    depends_on:
      - db
  db:
    image: mysql:latest
    command: mysqld --default-authentication-plugin=mysql_native_password
    volumes:
      - "./mysql:/var/lib/mysql"
    ports:
      - "3306:3306"
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=secret123
      - MYSQL_DATABASE=django_app
      - MYSQL_USER=django_app
      - MYSQL_PASSWORD=django_app123

Install MySQL Database Connector

Please read the official documentation here for more details. In order to use MySQL, we need a Python 3 database connector library compatible with Django. As per official documentation here. We need to install the Python and MySQL development headers and libraries like so. Add this line to the Dockerfile

RUN apt-get update
RUN apt-get install python3-dev default-libmysqlclient-dev  -y

We need to add mysqlclient to requirements.txt file.

Django==2.1.5
mysqlclient==1.3.14

Modify the Django Database settings as below, in the settings.py file.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_app',
        'USER': 'django_app',
        'PASSWORD': 'django_app123',
        'HOST': 'db',
        'PORT': '3307',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}

Test MySQL Connection to Application

We need to verify that the configurations in Django detect your MySQL server properly. We can do this by simply running the server. If it fails, it means that the connection isn’t working properly. Otherwise, the connection is valid. Run the below command to spin up the newly created setup.

docker-compose up

If you can access your server “http://localhost:8000” on a web browser to see the Django app. then everything is working perfectly.

Let us try to do something more with this application.

We will now follow the official Django documentation to create the polls app. Run the docker in detached mode by

docker-compose up -d

Create the polls app by

docker-compose exec app python3 /code/manage.py startapp polls

Before migrating the Db we have an issue with the latest version of MySQL mysql 8 new authentication method caching_sha2_password. So we need to execute the below commands.

log into MySQL console using the command below

docker-compose exec db mysql -uroot -psecret123

and then

ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'secret123';
exit;

Now, we can run migrations using the below command.

docker-compose exec app python3 /code/manage.py migrate --no-input

Follow the method as here to create your first view. Open the file polls/views.py. and modify it like below.

from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

Then create a file “polls/urls.py” and include the following code:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

Then open file “django_app/urls.py” modify it as below:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

If you navigate to “http://localhost:3000/polls/” you should see

Hello, world. You're at the polls index.

In this part, you built the initial base of your Django app. You have added and configured MySQL in Docker and connected MySQL to the Django backend.

Now we are running our Django app simply by executing

python3 manage.py runserver 0.0.0.0:8000

in the docker-compose.yml. This is the Django development server, a lightweight Web server written purely in Python. It is not intended for production application. It is not robust, has security issues, thread issues and etc. So, how do we really run our app then?

Well that is covered in this post.