How to Dockerize your application

Subham Misra
The Startup
Published in
4 min readMay 16, 2020

In my last post Docker None to Done, we discussed about docker architecture, basics of docker container creation, networking and docker volumes. In this post, let’s discuss about creating our own docker image using Dockerfile, distroless images and multi-stage builds.

Dockerfile is a descriptor file without any extension and it contains the instructions to be performed in order to build the desired image. For this demo we will use a simple python flask web application, which has two routes / and /docker

Python Flask webapp

Now we want to know the steps to get the application running, and we will include them in the Dockerfile. Let’s pull an ubuntu:16.04 image from docker hub and install python first, then we need to collect flask package using pip. After flask gets installed, we can copy our web application code in app.py file in container and run the below command.

After running the the above command, the application can be accessed using private IP of the docker container. Now we will run history command in the container to get all the steps we performed to get the application up and running.

Now we know what steps/instructions we require to run the application, let’s write the Dockerfile .

Sample Dockerfile

So, basically if you see the Dockerfile , first we have used the image ubuntu:16.04 as the base image layer. Then we have installed python, python-pip and the flask package using RUN command. In third step we have copied our app.py file from host directory to container’s \opt directory. At last, we have specified the command to launch the web application using ENTRYPOINT command.

Now, to build an image using this Dockerfile , we will run docker build command in the same folder where Dockerfile and app.py resides. We will use -t switch to tag the image. The . at last of the command denotes present working directory as build context.

docker build -t my-webapp .

This command takes some time and builds an image with the specified name. Now, to run the application image, we have to run the command :

docker run -d -p 3000:5000 my-webapp

Now the web application can be accessed at localhost:3000 address.

If we check the size of our newly built image, it’s of 423MB. Now, we want to reduce the image size. To achieve this we are going to use Multi-stage build and distroless image. As our web application is written in python, we are going to use python:2.7-slim as base image for the 1st stage build environment and gcr.io/distroless/python2.7-debian10 as our final stage build image. Let’s see how our updated Dockerfile looks like:

You can see in the Dockerfile , we have used two base images. First, we have declared python:2.7-slim image as our build environment and added the current directory as /app in build environment. Then we switched our working directory to /app and installed flask package using pip .

In the second stage, we are using a distroless image of python2.7 and copying /app and python site-packages directory from build environment to our second stage environment. After that, we are setting /app as our working directory and declaring PYTHONPATH environment variable. At last, using CMD command the app.py is getting executed. Basically, we are just using python:2.7-slim as our build environment to set up the execution environment for our application and discarding it. Now, let’s build the image.

docker build -t distroless-webapp .

Our distroless-webapp only takes 59.3 MB disk space while, my-webapp image which was built using single stage build, takes 423 MB. Now, we can run this distroless-webapp :

docker run -d -p 3000:5000 distroless-webapp

We can access the app at localhost:3000 address. So, there are two benefits using distroless image and multi-stage build, it takes lesser space and unnecessary packages are not present in the final build, which in turn reduces attack surface. Hope this was quite helpful :)

--

--