Docker Compose – Containerizing a Django Application

In the previous blog: Docker – Deep Dive, we created a Dockerfile with a set of instructions, started a service and create a container. Actual Projects are usually much more complex and require more than one services at a time running on multiple containers. Docker Compose handles exactly this.

Docker Compose is a tool to configure and run multiple containers that are inter dependent. It uses a YAML file to configure all the services and you can start/stop all of them with these commands:

Start services: docker-compose -f <filename.yaml> up

Stop services: docker-compose -f <filename.yaml> down

Django Application on Docker

As an example I am trying to run on docker, my Twitter Clone App that is built with Django and uses MySQL as the database: https://github.com/shilpavijay/TwitterClone

We will need a Dockerfile and docker-compose.yml file in the project directory.

Dockerfile:

FROM python:3.7-alpine
RUN apk update && apk add bash
RUN apk add gcc libc-dev linux-headers mariadb-dev
RUN pip install django djangorestframework django-rest-swagger PyJWT==1.7.1 gunicorn mysqlclient
COPY TwitterClone /app/TwitterClone
COPY TUsers /app/TUsers
COPY Tweets /app/Tweets
COPY manage.py /app
WORKDIR /app
EXPOSE 8000
CMD ["gunicorn","TwitterClone.wsgi","--bind=0.0.0.0:8000"]
  • In the above file, we are using a pre-built light weight image called alpine for python.
  • It then install all the required packages. Not specifying the version of the package will install the latest available version.
  • Next, all the project files and directories are copied to /app folder on the created container.
  • The current directory is changed to /app.
  • We also expose the port on which the application will run.
  • The last command will start the application.

docker-compose.yaml

version: '3.4'

services:
  db:
    image: mysql:5.7
    ports:
      - '3306:3306'
    container_name: twitter_db
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_DATABASE: 'twitterclone'
      MYSQL_USER: 'root'
      MYSQL_PASSWORD: 'guessme'
      MYSQL_ROOT_PASSWORD: 'guessme'

  twitterapp:
    container_name: twitterclone
    build:
      context: ./
      dockerfile: Dockerfile
    restart: always
    ports:
      - '8080:8000'
    volumes:
      - .:/code
    depends_on:
      - db
  • We have two services, one is the Django App (twitterapp) and the other is the MySQL DB (db). Ensure the names are always in lowercase.
  • The app will be built with the instructions in the Dockerfile.
  • MySQL container will be based on the mysql image available on docker hub. (refer previous blogpost)
  • The “depends_on” clause tells that the application has a dependency on the database.
  • MySQL service takes a while to start. There is usually a lag between the app start and database start time. To ensure a services does not fail if the other has not started yet, “restart: always” is configured.
  • Port forwarding is configured in the “ports:” clause. The host port 8080 is mapped to the container post 8000 on which the application is running. Hence, to access the application from the host system, we will be using port 8080.
  • We will discuss “volumes” in the subsequent section

Next, update settings.py in the Django Project with the host, port, login details to match that given in the Docker Compose file:

DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'twitterclone',
            'USER': 'root',
            'PASSWORD': 'guessme',
            'HOST': 'db',
            'PORT': '3306',
            },
        }

Then run, docker-compose -f <filename.yaml> up

When running the application for the first time OR if there are any changes to Django migrations, we need to run this explicitly in order to apply the migrations.

docker exec -it <container-id> python manage.py migrate

Then, execute the following commands to build and run the docker container:

docker-compose up --build

We are Done!!! The application should now be running on localhost:8080.

NOTE: Port already in use error:

If you have a DB running on your local on port 3306, do not forget to stop the service from Windows Services and then try running the docker-compose command. If you have a django app running on one of the ports specified in the docker composer file, you can either change the port number or close the running application

The complete code is here: https://github.com/shilpavijay/TwitterClone

Docker Volumes

Docker volumes are used for data persistence. When a container is stopped and re-run, the database starts all over again and the data stored previously is lost. To make it available even after the container is re-run, Docker volumes are made use of.

Here’s how it works. A directory from the host file system is mapped to a directory of the container file system. So, each time a container is started, the data is replicated into the host directory and when the container is restarted, it gets the data automatically from the directory in the host system.

Docker volumes can be created using the ‘docker run’ command. It can also be configured in the Docker Compose file.

There are 3 different types of docker volumes:

  • Host volume: User specifies the host directory where the data is to be replicated.
docker run -v /home/user/dockerdata:/var/lib/mysql/data
  • Anonymous volume: User does not specify the host directory. It is automatically taken care of, by docker. Only the directory on the container is specified.
docker run -v /var/lib/mysql/data
  • Named volume: User specifies a name but not the path. Path is handled by docker. You can reference the volume by the given name This type is most frequently used.
docker run -v name:/var/lib/mysql/data

Conclusion

In this blogpost series, we have leant the basics required to understand and use Docker. We have seen the Evolution of Docker, the need for docker and also how to setup and run an application on docker. We leant about Docker Compose and Docker Volumes too, in this post. Here are the links to previous posts:

Docker – Introduction

Docker – Deep Dive

Github link to the project discussed in this blog: https://github.com/shilpavijay/TwitterClone

You can also refer the official documentation page for more information and updates: https://docs.docker.com/get-started/

Author: Shilpa

https://kriyavikalpa.com/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s