Setup your first Python Flask Web Application on Docker Swarm

One of the cool things about Docker Swarm that I love, is the ability to scale your services into multiple replicas which resides on one or more nodes.

You get a lot of applications out there that can visually represent how it looks when it scales, and on which node your replicas reside and so forth.

But, I wanted to develop my own web application with Python and the Flask Framework, to respond with a random uuid and the container name where the request was received, so when I have one container, it will always display the same container name, but different uuid.

But with scaling, that is what I wanted to see, as soon as I scale my service, to be able to see the different container names.

Requirements: Docker Swarm:

You will need to have a Docker Swarm Cluster provisioned, if not, you can follow one of my blog posts to get Docker Swarm up and running.

Now to get to the Fun Stuff!

I like to use Alpine to keep my Docker images small, first we will create our directory, create our Dockerfile, Compose File and Application Code:

Create the Directory where our data will reside:

$ mkdir flask-demo
$ cd flask-demo

Our Dockerfile:

$ cat DockerfileFROM python:3.4-alpine
ADD . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

The application code:

$ cat app.pyfrom flask import Flask
import os
import uuid

app = Flask(__name__)

@app.route('/')
def index():
hostname = os.uname()[1]
randomid = uuid.uuid4()
return 'Container Hostname: ' + hostname + ' , ' + 'UUID: ' + str(randomid) + '\n'

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)

Python Package Dependencies:

$ cat requirements.txtflask

The Compose File:

You will see that my image in my compose file points to rbekker87/flask-containername which is a valid image on Docker Hub.

Also, I am exposing port 80 to the public, and translate that port to the container port on port 8080.

$ flask-app.ymlversion: '3.3'

services:
flask:
image: rbekker87/flask-containername
ports:
- "80:8080"
networks:
- appnet
deploy:
mode: replicated
replicas: 1
networks:
appnet:
driver: overlay

Deploy Time!

First we need to build our image and push our image to Docker Hub, Gitlab also offers a Docker Registry.

$ docker login (you will be prompted for your credentials)
$ docker build -t repository-name/image:tag .
$ docker push repository-name/image:tag

Now that we have our image push to our registry, we need to replace our image path in our compose file, once that is done, we will use docker stack to deploy our service to the swarm:

$ dokcer stack deploy --compose-file flask.yml apps --with-registry-auth

Once that is done, we can list our stack:

$ docker stack ls
NAME SERVICES
apps 1

We can also view the state, which node its running on, to list the tasks in our stack:

$ docker stack ps apps
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
265pty9lfv0c apps_flask.1 rbekker87/flask-containername:latest swarm-worker-01 Running Running 2 minutes ago

To get a view of the replicas, you can either inspect the service by running:

$ docker service inspect apps_flask

Or the get a Service View:

$ docker service ls -f name=apps
ID NAME MODE REPLICAS IMAGE PORTS
ak9chgrqsr28 apps_flask replicated 1/1 rbekker87/flask-containername:latest

Testing out our Python Flask Web App:

We only have one Replica for our Flask Service in our Swarm, so its expected that we will get the same container name. Make a couple of GET Requests to our Service:

$ curl -XGET http://swarm-pub-or-priv-ip/
Container Hostname: 4e6bd7a8a2bf , UUID: 771cc6bd-b669-4f68-83c6-cbb30ad01380
$ curl -XGET http://swarm-pub-or-priv-ip/
Container Hostname: 4e6bd7a8a2bf , UUID: c4f4115b-e848-4941-a399-b703afed249d

Let’s scale our Service to 2 Replicas, we can either update our compose file and run the deploy again, which will update our service, but I will use the docker service command to scale the service:

$ docker service scale apps_flask=2
apps_flask scaled to 2

To see some information about our replicas to confirm that the service scaled:

$ docker stack ps apps
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
265pty9lfv0c apps_flask.1 rbekker87/flask-containername:latest swarm-worker-01 Running Running 4 minutes ago
265pty9lfv0c apps_flask.2 rbekker87/flask-containername:latest swarm-worker-02 Running Running 2 minutes ago

Now, when we make GET Requests to our service you will find that the Requests will be routed via the Round Robin Routing Algorithm between the replicas:

$ curl -XGET http://swarm-pub-or-priv-ip/
Container Hostname: 9e6b28ba711f , UUID: 16780535-8c5f-445a-a1dd-fdb10e07bc59

$ curl -XGET http://swarm-pub-or-priv-ip/
Container Hostname: 4c3edef5c69b , UUID: ea496a8f-b49d-470b-a0f4-e695810374aa

Removing the Service from the Swarm:

To delete our Docker Stack:

$ docker stack rm apps

Resources:

The Docker Hub Repository that was mentioned can be found here:
- https://hub.docker.com/u/rbekker87/

For more Tutorials on Docker, feel free to give my blog a visit:
- https://sysadmins.co.za/

--

--

--

DevOps Engineer and Open Source Enthusiast

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

A Day in the Life: Grace Tan (Engineering Manager, WeWork)

Here’s How Salesforce Promotes Collaboration through Interoperability

Onboarding in Machine Learning Product Teams

March LeetCoding Challenge 2021 — Day 3: Missing Number

Launching Our Colors Rental Function

[LeetCode] Truncate Sentence

A Survival Guide: how to make it as a newly hired Software Engineer

Create AI Content Generator with Python Flask and OpenAI GPT-3

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ruan Bekker

Ruan Bekker

DevOps Engineer and Open Source Enthusiast

More from Medium

Build a CI pipeline with GitHub Actions for Python Project

Display recent queries on Web Page from PostgreSql database with Flask+psycopg2+Bootstrap

Deploy a Secure FastAPI App on Ubuntu 20.04 using Python3.10 / CertBot / Nginx and Gunicorn.

Optimize Docker Size Image with Python Environment