Dockerizing Flask Application Using Docker on Debian 10

Docker is an open-source tool designed to make it easier to create, deploy, and run applications by using containers. A container is a software package that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.

Flask is a popular Python web framework. It is classified as a microframework because it does not require particular tools or libraries. Compared to other frameworks it is lightweight and highly structured.

In this tutorial, we will explain how to deploy Flask application with Docker on Debian 10 server.

Prerequisites

  • A server running Debian 10.
  • A root password is configured on your server.

Getting Started

Before starting, it is a good idea to update your system's package to the latest version. You can update all the packages with the following command:

apt-get update -y
apt-get upgrade -y

Once all the packages are updated, restart your system to apply the changes.

Install Required Dependencies

Next, you will need to install the Nginx web server and other dependencies in your system. You can install all of them using the following command:

apt-get install nginx apt-transport-https ca-certificates curl gnupg2 software-properties-common curl -y

Once all the packages are installed, you can proceed to the next step.

Install Docker

By default, the latest version of Docker is not available in the Debian 10 repository. So it is a good idea to install it from the Docker official repository.

First, download and add the GPG key with the following command:

wget https://download.docker.com/linux/debian/gpg apt-key add gpg

Next, add the Docker repository with the following command:

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable"

Next, update the repository and install the Docker with the following command:

apt-get update -y
apt-get install docker-ce -y

Once the installation has been completed successfully, verify the status of the Docker with the following command:

systemctl status docker

You should get the following output:

? docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2020-04-19 06:26:25 UTC; 1min 8s ago
     Docs: https://docs.docker.com
 Main PID: 8883 (dockerd)
    Tasks: 10
   Memory: 46.6M
   CGroup: /system.slice/docker.service
           ??8883 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.413828757Z" level=warning msg="Your kernel does not support swap memory limit
Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.413876690Z" level=warning msg="Your kernel does not support cgroup rt period"
Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.413889604Z" level=warning msg="Your kernel does not support cgroup rt runtime
Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.414115814Z" level=info msg="Loading containers: start."
Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.788332166Z" level=info msg="Default bridge (docker0) is assigned with an IP a
Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.972022325Z" level=info msg="Loading containers: done."
Apr 19 06:26:25 debian10 dockerd[8883]: time="2020-04-19T06:26:25.010940205Z" level=info msg="Docker daemon" commit=afacb8b7f0 graphdriver(s)=o
Apr 19 06:26:25 debian10 dockerd[8883]: time="2020-04-19T06:26:25.011145541Z" level=info msg="Daemon has completed initialization"
Apr 19 06:26:25 debian10 systemd[1]: Started Docker Application Container Engine.
Apr 19 06:26:25 debian10 dockerd[8883]: time="2020-04-19T06:26:25.074603639Z" level=info msg="API listen on /var/run/docker.sock"

At this point, Docker is installed and running. You can now proceed to the next step.

Setup Flask Directory Structure

Next, you will need to create a directory structure to hold your Flask application.

Let's create a directory named flask inside the /var/www/ directory:

mkdir -p /var/www/flask

Next, change the directory to a flask and create the directory structure for flask:

cd /var/www/flask
mkdir -p app/static
mkdir -p app/templates

The static directory is used to store images, CSS, and JavaScript files while the templates directory is used to store the HTML templates for your project.

Next, you will need to create an __init__.py file inside the app directory:

nano app/__init__.py

Add the following contents to create a Flask instance and import the logic from the views.py file:

from flask import Flask
app = Flask(__name__)
from app import views

Save and close the file then create the views.py file in your app directory.

nano app/views.py

Add the following lines

from app import app
@app.route('/')
def home():
   return "hello world!"

Save and close the file then create the uwsgi.ini file with the following command:

nano uwsgi.ini

This file will contain the uWSGI configurations for our application as shown below:

[uwsgi]
module = main
callable = app
master = true

Save and close the file when you are finished. uWSGI is a deployment option for Nginx that is both a protocol and an application server.

Next, you will need to create the main.py file to imports the Flask instance named app from the application package. You can create it with the following command:

nano main.py

Add the following line:

from app import app

Save and close the file when you are finished. Next, create a requirements.txt file for specifying the dependencies that the pip package manager will install to your Docker deployment:

nano requirements.txt

Add the following line that matches with the latest version of Flask:

Flask==1.1.2

Save and close the file when you are finished.

At this point, your Flask application has been configured successfully. You can now proceed to the next step.

Configure Docker to Deploy Flask

Next, you will need to create a Dockerfile to build and deploy a flask application.

First, create a Dockerfile with the following command:

cd /var/www/flask
nano Dockerfile

Add the following lines:

FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
RUN apk --update add bash nano
ENV STATIC_URL /static
ENV STATIC_PATH /var/www/app/static
COPY ./requirements.txt /var/www/requirements.txt
RUN pip install -r /var/www/requirements.txt

Save and close the file when you are finished. Next, create a start.sh script to build an image from the Dockerfile and create a container from the resulting Docker image.

nano start.sh

Add the following line:

#!/bin/bash
app="docker.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
  --name=${app} \
  -v $PWD:/app ${app}

Save and close the file when you are finished.

Note : Make sure the port 56733 is free and usable.

Finally, run the script using the following command:

bash start.sh

This will create the Docker image and build a container from the resulting image as shown below:

Sending build context to Docker daemon  9.728kB
Step 1/6 : FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
python3.6-alpine3.7: Pulling from tiangolo/uwsgi-nginx-flask
48ecbb6b270e: Pull complete 
692f29ee68fa: Pull complete 
f75fc7ac1098: Pull complete 
c30e40bb471c: Pull complete 
Successfully built f5de17e1ce82
Successfully tagged docker.test:latest
22cd2bd23c9190cf2900fa1d7c55e4765a266e68c74dc1e6858872e9ebe7bdcd

You can now list the running containers with the following command:

docker ps

You should get the following output:

CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                            NAMES
22cd2bd23c91        docker.test         "/entrypoint.sh /sta…"   About a minute ago   Up About a minute   443/tcp, 0.0.0.0:56733->80/tcp   docker.test

You can also verify the Docker container by visiting the URL http://your-server-ip:56733. You should see the following screen:

Deploy Template Files

You can also deploy template files to serve static and dynamic content. You can create a home page template for your application with the following command:

nano app/templates/home.html

Add the following codes:

<!doctype html>

<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>Welcome Flask</title>
  </head>

  <body>
    <h1>Home Page</h1>
    <p>This is the home page of our flask application.</p>
  </body>
</html>

Save and close the file when you are finished. Next, you will need to modify the views.py file to serve the newly created file:

nano app/views.py

Update the file as shown below:

from flask import render_template

from app import app

@app.route('/')
def home():
   return "hello world!"

@app.route('/template')
def template():
    return render_template('home.html')

Save and close the file. Then, you will need to restart the Docker containers to apply the changes.

You can restart the Docker container named docker.test with the following command:

docker stop docker.test
docker start docker.test

Now, open your web browser and type the URL http://your-server-ip:56733/template. You should see your newly created template in the following screen:

Conclusion

Congratulations! you have successfully deployed a Flask application with Docker on Debian 10 server. You can now replicate the application across different servers with minimal reconfiguration. Feel free to ask me if you have any questions.

Share this page:

0 Comment(s)