When I’m at work I frequently encounter situations that could be quite messy. I was working on developing a supporting tool recently, that contained a Python Django-based app and another jar file that had to be invoked and sends the output to the Django app for the web dashboard to display the .jar file output.
It was really cumbersome. By then I had no idea about docker, my best bet was to:
- Configure host system to run the jar file smoothly
- Run the Django application inside a virtual environment
Both on a virtual machine. Setting the Django web application was the easy part, the difficult part was the Java environment. JDK vs JRE paths, versions, dependencies, … it was hell.
After that, I had an idea: since I have two almost-independent environments that need to run, and I need both to be kind of close to one another, why not learn Docker?
Ok, let me get something straight at first: this article doesn’t intend to teach you Docker nor Python nor Django. However, it should act as a reference of how to quickly “Dockerize” your application that is Django-based.
Ok, so let’s get to the commands and see how Dockerizing your django app could be achieved.
Creating a test Django app
Let’s create our sample Django application:
If you don’t have Django installed:
$ pip install django
This could be pip or pip3, depending on your own set up and if you’re using the default Ubuntu-shipped pip or not. You can run:
$ which pip
to know which pip is being invoked.
Creating the app
We will create a sample project called theproject.
$ django-admin startproject theproject # Let's go inside the directory and run it to test $ cd theproject/ $ python manage.py runserver
Now that the app is running fine, let’s “dockerize” it. To dockerize the app, we will need to create a Dockerfile to guide Docker on how to build the image that we need for this application to run. This includes dependencies, what port to expose to the outside world so that we can access the app from outside Docker, and many more settings that we will not tackle here (volumes, for instance.)
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /django_on_docker/ COPY requirements.txt /django_on_docker/ WORKDIR /django_on_docker RUN pip install -r requirements.txt COPY . /django_on_docker EXPOSE 8000 CMD ["ls"] CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
What we wrote basically was importing the default Python image, create a directory in the container, copy requirements.txt if we have one, to mention our dependencies (in our case, it’s “Django==2.2.6”)
If we’re not sure, we can use pip freeze > requirements.txt command to generate a txt file of the current installed packages.
Creating the image
$ docker build -t testdjango .
You might have some sudo problems if you’re on Ubuntu. The previous command builds an image and calls it “testdjango” from the Dockerfile in the path “.” (current directory)
Sending build context to Docker daemon 20.48kB Step 1/11 : FROM python:3 ---> 02d2bb146b3b Step 2/11 : ENV PYTHONUNBUFFERED 1 ---> Using cache ---> f189027eb76f Step 3/11 : RUN mkdir /django_on_docker ---> Using cache ---> 00cbac3a8583 Step 4/11 : COPY requirements.txt /django_on_docker/ ---> f18487ddaee8 Step 5/11 : WORKDIR /django_on_docker ---> Running in f17fe8db4a7e Removing intermediate container f17fe8db4a7e ---> 9d260da6f98f Step 6/11 : RUN pip install -r requirements.txt ---> Running in f00e52ca07b8 Collecting Django==2.2.6 (from -r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/b2/79/df0ffea7bf1e02c073c2633702c90f4384645c40a1dd09a308e02ef0c817/Django-2.2.6-py3-none-any.whl (7.5MB) Collecting sqlparse (from Django==2.2.6->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/ef/53/900f7d2a54557c6a37886585a91336520e5539e3ae2423ff1102daf4f3a7/sqlparse-0.3.0-py2.py3-none-any.whl Collecting pytz (from Django==2.2.6->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/e7/f9/f0b53f88060247251bf481fa6ea62cd0d25bf1b11a87888e53ce5b7c8ad2/pytz-2019.3-py2.py3-none-any.whl (509kB) Installing collected packages: sqlparse, pytz, Django Successfully installed Django-2.2.6 pytz-2019.3 sqlparse-0.3.0 Removing intermediate container f00e52ca07b8 ---> 313f0daa51db Step 7/11 : COPY . /django_on_docker ---> 94c34b7e0786 Step 8/11 : WORKDIR /django_on_docker/ ---> Running in eadfe9421c59 Removing intermediate container eadfe9421c59 ---> b8767b36c53f Step 9/11 : EXPOSE 8000 ---> Running in 5917cb5c3789 Removing intermediate container 5917cb5c3789 ---> 8137bb6fdfe6 Step 10/11 : CMD ["ls"] ---> Running in 83d1a91ce005 Removing intermediate container 83d1a91ce005 ---> ec5558b57984 Step 11/11 : CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] ---> Running in 4ce8bea1af13 Removing intermediate container 4ce8bea1af13 ---> fb67dd3ed80f Successfully built fb67dd3ed80f Successfully tagged testdjango:latest
As we can see, Docker built the image and installed Django for us, and also run the commands that we mentioned and it should now be up and running!
So, now we can create a container based on the image that we had built.
$ docker run -p 8000:8000 testdjango
Of course there are many options we’re omitting: volumes, naming the container, user namespace, running in interactive mode and more. Just for the sake of getting things up and running fast!
I might look into writing about that in a following series!
Now we can go to our localhost via the browser, on port 8000 and we find that it’s up and running! If things go smooth, you’re probably happy that Dockerizing your Django app didn’t take that long!