Docker+Django+MySQL

Views: 205
Wrote on April 16, 2020, 9:08 p.m.

In last Chapter we successfully built a Django project in docker container, but the database we used was SQLite, which is not recommended in production. To be clear, I don't agree with the saying that "you can’t use SQLite in production", data of this website is stored in SQLite, and it's quite stable, the data reading speed or efficiency is never a problem, SQLite is not directly comparable to client/server SQL database engines such as MySQL, Oracle, PostgreSQL, or SQL Server since SQLite competes with fopen(). In this chapter, we are going to talk about setting up Django on MySQL in Docker containers.

Preparation

If you have MySQL installed on host machine and running on 3306 port, make sure to stop the service first:

$ sudo /etc/init.d/mysql stop
// you can later run 
$ sudo /etc/init.d/mysql start
// to restart the service

Docker-compose

The idea of object-oriented programming tended to separate modules with independent functions to facilitate reuse and maintenance. Container is the same. Although it is theoretically possible to cram all components into the same container, it is better to keep the modules in separate containers as long as the communication between them is well maintained. That is to say, we are going to see two containers in this Chapter: app: container for Django db: container for MySQL

First, we edit the docker-compose.yml created in previous chapter.

version: "3"
services:
  app:
    restart: always
    build: .
    command: bash -c "python3 manage.py migrate && python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: mysql:5.7
    volumes:
      - "./mysql:/var/lib/mysql"
    ports:
      - "3306:3306"
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=P4S5WoRd
      - MYSQL_DATABASE=dockerDemo

depends_on does not wait for db to be “ready” before starting web only until they have been started.

Why do we use volumes here? Can we just keep data in a container and keep it isolated? Keeping the data in the container is theoretically possible, but there is a fatal problem because the data is linked to the life cycle of the container, imagine what if the container is deleted one day, the data in it will follow the wind and pass away with it, you'll then become the legendary figure in your company. Be aware that the life cycle of the container may be very short, and the delete instruction is also quite smooth (just typing docker-compose down and it's gone). Thus we map the data to the localhost machine, even if the container is deleted, the data is still lying safely on your server. In other words, container is suitable for running stateless applications; when it comes to stateful things like data, you must think about it carefully.

In our case, you'll later find a folder called "mysql" created under the project root folder, that's where we are going to store the data thru MySQL container, this has nothing do to with your local MySQL, even you do not have it installed on host machine. - "./mysql:/var/lib/mysql"means we expose a local folder ./mysql to MySQL docker container for data storage, just like how ports works.

Dockerfile

Now we edit the Dockerfile.

FROM python:3.6
ENV PYTHONUNBUFFERED 1

# Add these two lines
RUN apt-get update
RUN apt-get install python3-dev default-libmysqlclient-dev -y

RUN mkdir /code
WORKDIR /code
RUN pip install pip -U
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

Activate your local virtual environment,

$ source bin/activate
$ cd demo
$ pip install mysqlclient
$ pip freeze > requirements.txt

You'll see mysqlclient==1.4.6 or whatever version of mysqlclient was just added.

Django Settings

Now let's modify database connection information in Django settings.py

ALLOWED_HOSTS = ['*']
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dockerDemo',
        'USER': 'root',
        'PASSWORD': 'P4S5WoRd',
        'HOST': 'db', # Not localhost
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}

Go For Launch

$ sudo docker-compose build
$ sudo docker-compose up

Believe or not, you can even edit your code without turn it off, docker and django will hot watch any of your update and automatically apply it on your browser, it is cool, isn't it? Develop in contain environment is not recommended.