Flask web app with Bulma frontend run on Docker with Prometheus metrics.

Simple example web application displays hostname and network address. We used Flask, Bulma with Prometheus and container.

ยท

5 min read

Flask web app with Bulma frontend run on Docker with Prometheus metrics.

Purpose

This post we sharing our experience building web app with Flask server backend and CSS Bulma frontend. The source code of application will be explained in detail needed to illustrate technical concept. The business concept is to have an application:

  • web based and good looking - support modern CSS framework ๐Ÿ‘
  • displaying host and network information - our business ๐Ÿ’‘ requirements
  • easy to deploy and monitor - container based ๐Ÿ“ฆ with easy metrics

Assumptions

We asssume the you are avare of Prometheus metrics, know how to build and run Docker containers, and understand Flask framework.

Web application with Flask and Bulma CSS

While this is very simple application we can go via this step by step. You have to

git clone https://github.com/koperak/simpleapp.git && cd simpleapp
docker build . -t simpleapp
docker run -d -p 5000:5000 simpleapp

and point to http://127.0.0.1:5000/ to see it in action.

Let's go through the project structure:

|   .dockerignore
|   .gitignore
|   app.py
|   Dockerfile
|   README.md
|   requirements.txt
|
\---templates
        index.html
  • requirements.txt file have Python requirements for application, they are latest version of Flask and Prometheus library for Flask

  • app.py and templates\index.html are main files for simple Flask application, in this case it contains business logic and template for view. This is not optimal Flask application structure and you would like to avoid it in your production code. Instead apply for best practices from Flask experts.

So you are warned and I am going into the app.py file which have some crucial parts:

  • initialization of templating for Flask and metrics for prometheus, which are dependencies described in requirements.txt file:
from flask import Flask, render_template
from prometheus_flask_exporter import PrometheusMetrics

app = Flask(__name__)
metrics = PrometheusMetrics(app)
  • rendering index.html template with additional parameters and serving it on / path:
@app.route("/")
def index():
    return render_template('index.html', server_ip = server_ip, server_name = server_name)
  • simple logic to deliver business requirements:
import socket

try: 
    server_name = socket.gethostname() 
    server_ip = socket.gethostbyname(server_name) 
except: 
    server_name = "Unable to get Hostname"
    server_ip = "Unable to get IP"

Jinja based template index.html file contains:

  • main page for application with Bulma CSS styles included:
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
  • variables with some values that are coming from main application file, they are rendered as Jinja expressions having Bulma's title class :
<h1 class="title">
  {{ server_ip }} 
  {{ server_name }}
</h1>

Our sample application is packed into Docker container which instruct Docker image building command docker build . -t sampleapp to do the following:

  • start from base image which is required by Flask application FROM python:3.9-alpine

  • create and go into code directory inside container where our source code will be located by COPY . /code

  • set environment variables for Flask application if you want to know more please study Flask documentation

  • installing required libraries RUN pip install -r /code/requirements.txt

  • EXPOSE 5000 instruct other users of this container image that we are exposing some service on HTTP port 5000

  • finaly previously installed flask library is run

And there are some additional files:

  • .dockerignore contains files and directories we don't want to be included in out container, usually those are secrets, logs or workspace specific directories.

  • .gitignore contains files and dirs we don't want track with source control system for example secrets, binaries and other compilates, it is shared from Python project to project so contains quite a lot files.

Summary

When you run container and browse to http://127.0.0.1:5000/ you will see nice looking web application which supports our business ๐Ÿ’‘ users. But there is also one more path http://127.0.0.1:5000/metrics which deliver expected monitoring ๐Ÿ”ฆ functionality.