Dockerizing a Django App - for complete starters

mahyess

Mahesh Prajapati

Posted on January 19, 2022

Dockerizing a Django App - for complete starters

As starters, the term docker can be quite daunting and may seem a big cliff to overcome but it shouldn't be as such.

The vast amounts of tutorials covering a lot of information at once, doesn't help the starters, speaking from personal experience. That's why, this post is a single step towards the complete new world of docker. So, let's begin.

First thing first, you need to have a existing Django project that you are willing to Dockerize.

I have created a new Django project for this very purpose and going to use it as a starting template. Let's see files that are here inside this folder.

├── db.sqlite3
├── manage.py
├── requirements.txt
└── todo
    ├── asgi.py
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
Enter fullscreen mode Exit fullscreen mode

As a complete boilerplate, when run the server with python manage.py runserver, we are presented with our starting page.
Django Starting Page

So far, so good.

Let's create a file named Dockerfile in the root directory. The files tree needs to look like

├── db.sqlite3
├── Dockerfile
├── manage.py
├── requirements.txt
└── todo
    ├── asgi.py
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
Enter fullscreen mode Exit fullscreen mode

Now, let's quote what Dockerfile is:

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.

This is where we put the commands to build our image.

FROM python:3.10

RUN mkdir /app

COPY requirements.txt /app/

WORKDIR /app

RUN pip install -r requirements.txt

COPY . /app/

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Enter fullscreen mode Exit fullscreen mode

Let's go through these commands one by one.

1.

FROM python:3.10-slim
Enter fullscreen mode Exit fullscreen mode

We are using python:3.10-slim as our base image from which we build our image. We can use python:3.10 but it will generate larger build file, which we should be trying to reduce. Also, we can use python:3.10-alpine which reduces the size even further, but this will require extra care from our end. That's a topic for some other time. If you are interested in knowing further, you can go through here.

2.

RUN mkdir /app
Enter fullscreen mode Exit fullscreen mode

It is pretty straight-forward. It creates a new directory called app in root directory of the image.

3.

COPY requirements.txt /app/
Enter fullscreen mode Exit fullscreen mode

It copies the requirements.txt file from our project to the directory we just created. If you don't have this file yet, you can create one by entering the command pip freeze > requirements.txt which gets all packages that are currently installed in our django project and writes them into the said file.

4.

WORKDIR /app
Enter fullscreen mode Exit fullscreen mode

It sets the current working directory to the directory we created. In other words, we cded to this directory. Any commands we enter from herein are triggered from this directory.

5.

RUN pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

The image we used from line 1, python:3.10-slim as pip installed into it by default. So we can run any pip commands in the image. This command installs all the packages that we had installed in our local system previously.

6.

COPY . /app/
Enter fullscreen mode Exit fullscreen mode

Similar to line 3, but now we copy all files and folders in the local system into the image. Now, why didn't we did this in line 3 itself? If you wondered, that's good. It's because docker caches all the commands while building the image, so if we haven't changes requirements.txt further down the line in future, all commands from 1-5 aren't triggered again. Else, even if there aren't any changes in packages, but have changes in our project, docker will unnecessarily installs all the packages again.

7.

EXPOSE 8000
Enter fullscreen mode Exit fullscreen mode

We are almost done. It exposes the port 8000 to "outside world" from image. Since we are going to run Django in port 8000, this is a gateway to the server we are going to run later.

8.

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Enter fullscreen mode Exit fullscreen mode

Finally, it runs the command python manage.py runserver 0.0.0.0:8000 inside the image. That means, our server will now be up and running.

We have completed writing a very basic Dockerfile that works. Now, head up to the terminal and enter the command:

docker build -t todo/latest .
Enter fullscreen mode Exit fullscreen mode

Let's wait for some time as docker builds our image. If you are wondering what's todo/latest, its a tag name. You can put anything as you want or even skip it to just run docker build ., but we will have to search for our image by going to through a list of images built in the system by going through docker ps. Let's not go out of our way for now. If you are interested, you can certain try it by yourself.

So, after waiting a couple of minutes, or seconds, depending on several factors, to complete the build, let's trigger the final command.

docker run -p 8000:8000 todo/latest
Enter fullscreen mode Exit fullscreen mode

This command runs the CMD that we have provided in the Dockerfile. As for 8000:8000, we are binding our local port 8000 to the image's port 8000. If you wish, you can put 80:8000, so it binds to local port 80 to the image's port.

If everything goes well, your terminal should get a normal Django server log. For me, it's

╰─ docker run -p 8000:8000 todo/latest
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
January 19, 2022 - 11:55:15
Django version 4.0.1, using settings 'todo.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
Enter fullscreen mode Exit fullscreen mode

Let's check our browser for confirmation. We should be presented again with this beautiful page.

Django Starting Page

Congratulations, you have successfully "Dockerize" your Django application.

As for the migrations warnings, you can add a line RUN python manage.py migrate after line 6 and before line 8, and build again.

This is a very basic Dockerfile as mentioned. I want it to be understood by a complete beginner so haven't included a number of "gotcha"s to the Dockerfile, they can be learnt as we go and code.

The complete code can be found in my GitHub. Feel free to check it out, if you are having any problems.

💖 💪 🙅 🚩
mahyess
Mahesh Prajapati

Posted on January 19, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related