Containerizing a Django app with Docker and Docker-compose
Running application components in containers
In the previous article I introduced docker to you and showed how it can be used with a Django project. We also saw how we can run an app in a container in our local system.
In this write up, I will be taking it a step further with the same codebase which we'll fetch from github, showing how to run different services used by our application by employing a more effective tool for this use-case, called docker compose. For example, if our application has a database service, cache service etc., each of this services can be run together but in separate containers or environment and and our application would still work as expected. The instructions for the different services are usually defined in YAML file usually name docker-compose.yml.
Fetch our code from github.com/toyetola/tutorial
To fetch, RUN
github clone https://github.com/toyetola/tutorial
You would see your project cloned into #tutorial directory
Now create a file docker-compose.yml in the root folder named tutorial
version: "3.9"
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
This file is uses a version of docker-compose 3.9. It hen introduces that makes up our application with the keyword 'services'. The 'web' service uses the Dockerfile in the project root directory to build the project and then runs the coomand on a local ip in the container and on the container port 8000. The command maps the host system port to the container's port 8000.
I will like to intruduce a database other than the default SQLITE database as we are running a multi-container system and we need to show that in our compose file and see how these indivdual containers that runs the different parts of our applications comes to work together.
Go to settings.py in your project folder and edit the DATABASE section to reflect the following changes:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': env('POSTGRES_NAME'),
'USER': env('POSTGRES_USER'),
'PASSWORD': env('POSTGRES_PASSWORD'),
'HOST': env('DATABASE_HOST'),
'PORT': env('PORT')
}
}
Create a .env
file in the root directory of your project, this stores your environment variables as it best practice to not use actual values of your secret keys and other database config values in your settings file. To make the .env file readable from settings.py, you will nead a django package that helps with this named django-environ
RUN python -m pip install django-environ
In setting.py:
At the top of the file after the Path import
import os
import environ
Cast DEBUG to default to FLASE if not read from .env
env = environ.Env(
DEBUG = (bool, False)
)
#Take environment variables from .env file
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
Your .env
file looks like this:
SECRET_KEY=django-non-serious-key&blatheblafkfhh&^%dhhdh(@&*JHFG*
POSTGRES_NAME=example
POSTGRES_USER=mydbuser
POSTGRES_PASSWORD=mydbpassword
DATABASE_HOST=192.168.23.4
DEBUG=1
DATABASE_PORT=5432
Please note: that you would need to down POSTGRESQL on your machine. You can easily do this by downloading PgAdmin. This helps you with a lot of setup automatically.
When you install PgAdmin, this is the interface that allows you login as a user or create a user account.
Now update the docker-compose.yml
file with the following code which represent the database service and defines the structure on which the container for this service is built.
services:
db:
image: postgres
volumes:
- ./data/db:/var/lib/postgresql/data
environment:
- POSTGRES_NAME=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
environment:
- POSTGRES_NAME=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
depends_on:
- db
Next RUN docker-compose up
to build and export a container image of our entire application.
You will see in your docker desktop your running container services
When you click on the "open in browser" button that shows up hovering on the tutorial_web_1 container service, it leads you to localhost:8000 with this view.
To see your applications image created by docker
RUN dock image ls
Let share our app, we could share it to any online registry e.g. Dockerhub, Google Container registry etc. We would be using docker hub, you might wan to create an account on hub.docker.com. Login via your docker desktop
In your terminal, while in the root directory of your project;
Now tag your image to specify how it will be uploaded to docker hub
RUN docker tag <IMAGE-ID> yourdockerhubusername/tutorial_web:v1
e.g.
docker tag 9ad4ec1c5b59 yourdockerhubusername/tutorial_web:v1
Push to docker hub
RUN docker push yourdockerhubusername/tutorial_web:v1
VIOLA!!!
We just got our application and its dependent services running in containers. Let me know if this has helped you and if you have questions I am available to answer your questions in the comments.
Check this branch for correct code: github.com/toyetola/tutorial/tree/compose-l..