Skip to content

sjfke/flask-play

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build and Run a Flask Docker container

Building the docker image uses Docker for Windows on Windows 10 Home edition where only WSL 2 is available.

With Windows 10 Pro you can choose to use a Hyper-V backend or WSL 2.

The documentation shows

  • running podman and podman-desktop on Linux but it is also possible on Windows.
  • running docker and docker-desktop on Windows but it is also possible on Linux.

Podman Prep Instructions

# Create podman volumes
sjfke@morpheus$ podman volume create postgres-flask-play
sjfke@morpheus$ podman volume create mongodb-flask-play
sjfke@morpheus$ podman volume create mongoconfigdb-flask-play

Podman Compose Instructions

Uses the same compose.yaml written for the docker approach.

# Using compose.yaml file
sjfke@morpheus$ podman compose -f ./compose.yaml up -d mongo # start MongoDB container
sjfke@morpheus$ podman exec -it flask-play-mongo-1 mongosh mongodb://root:example@localhost:27017 # mongosh
# Add contents as described in 'tests\momgodb-test-data.txt'

# Using compose.yaml file
sjfke@morpheus$ podman play kube --start ./pods/flask-play-mongo.yaml
sjfke@morpheus$ podman exec -it flask-play-mongo-1-pod mongosh mongodb://root:example@localhost:27017 # mongosh
# Add contents as described in 'tests\momgodb-test-data.txt'

# Define variables
sjfke@morpheus$ export CONTAINER_NAME="crazy-frog"
sjfke@morpheus$ export IMAGE_NAME= "localhost/flask-play"

# Build image
sjfke@morpheus$ podman build --tag $image --no-cache --squash -f ./Dockerfile
sjfke@morpheus$ podman image ls $image

# Run, test, delete container
sjfke@morpheus$ podman run --name $name -p 8080:8080 -d $image
sjfke@morpheus$ podman logs ${CONTAINER_NAME}
sjfke@morpheus$ podman exec -it ${CONTAINER_NAME} sh
sjfke@morpheus$ podman kube generate ${CONTAINER_NAME} -f ./pods/flask-play-web-1.yaml # generate pod manifest
sjfke@morpheus$ /usr/bin/firefox http://localhost:8485
sjfke@morpheus$ podman rm --force $name

# Image Maintenance
sjfke@morpheus$ podman image prune

Podman Play Kube Instructions

# Preparation
sjfke@morpheus$ sudo dnf install jq   # ensure 'jq' is installed
sjfke@morpheus$ podman network create flask-play_net
sjfke@morpheus$ podman inspect flask-play_net | jq '.[].subnets.[].subnet'
"10.89.0.0/24"

# Create DataBase secrets (TODO)
# sjfke@morpheus$ podman secret create --env=true my_secret MYSECRET

# Using Play Kube Pod files 
sjfke@morpheus$ podman play kube --start ./pods/flask-play-mongo.yaml --net flask-play_net
sjfke@morpheus$ podman exec -it flask-play-mongo-1-pod mongosh mongodb://root:example@localhost:27017 # mongosh
# Add contents as described in 'tests\momgodb-test-data.txt'

# Run, test, delete container using podman play kube
# NOTE: 'flask-play-flask' needs to be started before 'flask-play-nginx'
sjfke@morpheus$ podman play kube --start ./pods/flask-play-dbgate.yaml --net flask-play_net
sjfke@morpheus$ podman play kube --start ./pods/flask-play-mongo.yaml --net flask-play_net
sjfke@morpheus$ podman play kube --start ./pods/flask-play-postgres.yaml --net flask-play_net
sjfke@morpheus$ podman play kube --start ./pods/flask-play-flask.yaml --net flask-play_net
sjfke@morpheus$ podman play kube --start ./pods/flask-play-nginx.yaml --net flask-play_net

# Build
sjfke@morpheus$ podman play kube --build ./pods/flask-play-flask.yaml
sjfke@morpheus$ podman play kube --build ./pods/flask-play-nginx.yaml

# Reload, Restart
sjfke@morpheus$ podman play kube --reload ./pods/flask-play-flask.yaml
sjfke@morpheus$ podman play kube --reload ./pods/flask-play-nginx.yaml

# Start all pods
sjfke@morpheus$ for pod in 'postgres' 'mongo' 'dbgate' 'flask' 'nginx'; do
  podman pod ps | grep -q flask-play-${pod}  || podman play kube --start ./pods/flask-play-${pod}.yaml --net flask-play_net
done

# Stop and delete all pods
sjfke@morpheus$ for pod in 'postgres' 'mongo' 'dbgate' 'flask' 'nginx'; do
  podman pod ps | grep -q flask-play-${pod}  && podman play kube --down ./pods/flask-play-${pod}.yaml
done

sjfke@morpheus$ /usr/bin/firefox http://localhost:8485
sjfke@morpheus$ podman play kube --down ./pods/flask-play-web.yaml

# Development, test (wash repeat cycle)
sjfke@morpheus$ export IMAGE="docker.io/library/flask-play-flask"
sjfke@morpheus$ export CONTAINER=$( basename $IMAGE)
sjfke@morpheus$ podman build --tag ${IMAGE} --no-cache --squash -f ./flask/Dockerfile
sjfke@morpheus$ podman play kube --replace ./pods/${CONTAINER}.yaml --net flask-play_net
sjfke@morpheus$ /usr/bin/firefox http://localhost:8485

Docker Compose

# Create docker volumes
PS C:\Users\sjfke> docker volume create postgres-flask-play
PS C:\Users\sjfke> docker volume create mongodb-flask-play
PS C:\Users\sjfke> docker volume create mongoconfigdb-flask-play

# Once compose.yaml is created, see references (ii, iii)
PS C:\Users\sjfke> docker compose -f .\compose.yaml up -d mongo # start MongoDB container
PS C:\Users\sjfke> docker exec -it flask-play-mongo-1 mongosh mongodb://root:example@localhost:27017 # mongosh
# Add contents as described in 'tests\momgodb-test-data.txt'

# Start the whole application
PS C:\Users\sjfke> docker compose -f .\compose.yaml up -d # builds flask-play-web image
PS C:\Users\sjfke> start http://localhost:8485
PS C:\Users\sjfke> start http://localhost:8486           # admin/admin
PS C:\Users\sjfke> docker compose -f .\compose.yaml down 

# Development, test (wash repeat cycle)
PS C:\Users\sjfke> docker compose -f .\compose.yaml down web
PS C:\Users\sjfke> docker compose build web
PS C:\Users\sjfke> docker compose -f .\compose.yaml up -d web
PS C:\Users\sjfke> start http://localhost:8485
  1. Docker: Overview of Docker Compose
  2. Docker: Compose specification
  3. Docker: Compose specification - ports

Docker Build instructions

# Define variables
PS C:\Users\sjfke> $name = "crazy-frog"
PS C:\Users\sjfke> $image = "localhost/flask-play"

# Build image
PS C:\Users\sjfke> docker build --squash -t $image -f .\Dockerfile $PWD
PS C:\Users\sjfke> docker image ls $image

# Run, test, delete container
PS C:\Users\sjfke> docker run --name $name -p 8080:8080 -d $image
PS C:\Users\sjfke> docker exec -it $name sh
PS C:\Users\sjfke> docker logs $name
PS C:\Users\sjfke> start http://localhost:8485
PS C:\Users\sjfke> docker rm --force $name

Docker Image Maintenance

PS C:\Users\sjfke> docker image prune # clean up dangling images
PS C:\Users\sjfke> docker system prune 
PS C:\Users\sjfke> docker rmi $(docker images -f 'dangling=true' -q)       # UNIX, images with no tags
PS C:\Users\sjfke> $d = docker images -f 'dangling=true' -q; docker rmi $d # Powershell, images with no tags

Postgresql modifications

Create the auth database

$ podman exec -it flask-play-posgres-1 /bin/bash
root@79685c6f4e96:/# createdb auth
root@79685c6f4e96:/# exit

22.2. Creating a Database

Need to grant podman flask-play_net network access to create the tables and use the auth database.

$ podman network inspect flask-play_net | grep subnet -A 5 | head -n 8
          "subnets": [
               {
                    "subnet": "10.89.0.0/24",
                    "gateway": "10.89.0.1"
               }
          ],
          "ipv6_enabled": false,
          "internal": false,

Update postgresql 'pg_hba.conf' file

$ podman cp flask-play-postgres-1:/var/lib/postgresql/data/pg_hba.conf .
$ gedit pg_hba.conf       
$ cat /tmp/pg_hba.conf 
# ...
# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# Podman flask-play_net IPv4 local connections:
host    all             all             10.89.0.4/24            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     trust
host    replication     all             127.0.0.1/32            trust
host    replication     all             ::1/128                 trust

$ podman cp pg_hba.conf flask-play-postgres-1:/var/lib/postgresql/data/pg_hba.conf
$ podman restart flask-play-postgres-1

To create the tables, for the auth database.

$ podman exec -it flask-play-web-1 /bin/ash
/usr/src/app # python create-postgresql-tables.py 
/usr/src/app # exit

Flask, Jinja and Python References

Flask, MongoDB References

Nginx References

Useful References

Bootstrap References

Markdown References

This repository provides a simple Python web application implemented using the Flask web framework and executed using gunicorn. It is intended to be used to demonstrate building and test of Python Flask web applications using Docker

Building the docker image uses Docker for Windows on Windows 10 Home edition where only WSL 2 is available. With Windows 10 Pro you can choose to use a Hyper-V backend or WSL 2.

Application's Key files:

  • config.py: GUNICORN settings;
  • wsgi.py: define the pages (routes) that are visible;
  • static: several bootstrap themes from Bootstrap 4 themes
  • templates/base.html: boiler-plate for all html pages;
  • templates/index.html: Standard Lorem Ipsum;
  • templates/legal.html: Legal-style Lorem Ipsum;
  • templates/pirate.html: Pirate-style Lorem Ipsum;
  • templates/zombie.html: Zombie-style Lorem Ipsum

None of the bootstrap themes are enabled be default, edit templates/base.html to activate them.

Implementation Notes

This sample Python application deploys a WSGI application using the gunicorn WSGI server. The requirements which need to be satisfied for this to work are:

  • The WSGI application code file needs to be named wsgi.py.
  • The WSGI application entry point within the code file needs to be named application.
  • The gunicorn package must be listed in the requirements.txt file for pip.
  • The requirements.txt file is generated using pipenv run pip freeze > requirements.txt.

The example is derived from Getting Started with Flask but has been modified to use BootStrap 4, work with Green Unicorn - WSGI sever, the content of the web-site changed to provide a sandbox for testing Flask

Other useful references:

Docker File

A simple Docker file which using, python:3-alpine container, first it pip installs the required applications specified in the requirements.txt file, copies the application files to the container, and finally, sets up the environment and starts gunicorn.

FROM python:3-alpine
# TODO: Put the maintainer name in the image metadata
MAINTAINER Sjfke (Geoff Collis) <gcollis@ymail.com>

# TODO: Rename the builder environment variable to inform users about application you provide them
ENV BUILDER_VERSION 1.0

# TODO: Set labels used in OpenShift to describe the builder image
LABEL io.k8s.name="Flask" \
      io.k8s.description="Sandbox for Flask Application for Docker" \
      io.k8s.display-name="Flask Sandbox" \
      io.k8s.version="0.1.0" \
      io.openshift.expose-services="8080:http" \
      io.openshift.tags="Sandbox,0.1.0,Flask"

ENV PORT=8080
WORKDIR /usr/src/app

# Project uses 'pipenv' (Pipfile, Pipfile.lock), Docker needs requirements.txt
# $ pipenv run pip freeze > requirements.txt # generates requirements.txt
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# TODO (optional): Copy the builder files into /opt/app-root
# COPY ./<builder_folder>/ /opt/app-root/
COPY config.py ./
COPY static/* ./static/
COPY templates/* ./templates/
COPY wsgi.py ./

# TODO: Copy the S2I scripts to /usr/libexec/s2i, since openshift/base-centos7 image
# sets io.openshift.s2i.scripts-url label that way, or update that label
# COPY ./s2i/bin/ /usr/libexec/s2i

# TODO: Drop the root user and make the content of /opt/app-root owned by user 1001
# RUN chown -R 1001:1001 /opt/app-root

# This default user is created in the openshift/base-centos7 image
USER 1001

# TODO: Set the default port for applications built using this image
EXPOSE ${PORT}

# TODO: Set the default CMD for the image
CMD gunicorn -b 0.0.0.0:${PORT} wsgi

MongoDB

PS1> docker exec -it flask-play-mongo-1 mongosh --username root

About

Sandbox for testing docker and flask

Resources

License

Stars

Watchers

Forks

Packages

No packages published