Flask is a beautiful micro-framework in python for web development. In this article, we’ll see how to deploy it on your personal favourite cloud infrastructure using Docker!
The entire code for this article is available here.
We will create a hello-world Flask application and host it using a Gunicorn server. Note that Flask apps can be normally hosted using the in-built debug server, but it isn’t great for production.
While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well ~ Flask docs
That is why we use a WSGI server. Gunicorn is simple and reliable.
Docker is the company driving the container movement and the only container platform provider to address every application across the hybrid cloud. ~ Docker
A container is a logical package for an application which provides an environment for it to run. It is a virtualized environment, containing the code, libraries and everything else. Containers make it easy to run the software anywhere without any conflicts from the environment it is running in!
Docker packages software into standardized units for development, shipment, and deployment — https://www.docker.com/what-container
Docker is a container-platform. More about dockers here.
Create a folder for this activity and navigate into it. We’ll use this to store the source code for our app.
$ mkdir flask-app
$ cd flask-app
We will write a very basic web app in Flask which returns a hello-world on the ‘/’ endpoint.
The server code will look like this:
from src import app
from flask import Flask, jsonify
@app.route('/')
def index():
return jsonify(message="hello, world!")
It simply creates an endpoint at ‘/’ and returns the JSON:
{message: "hello, world!"}
We also write two more files for our app:
__init__.py — to create the app instance
from flask import Flask app = Flask(__name__) from .server import *
flask gunicornMove all the code in the ‘src’ folder and the file tree should look like that in the figure.
Let’s quickly fire up the terminal and test this server!
$ pip3 install -r src/requirements.txt
$ gunicorn src:app
‘/’ serving hello-world!
Now that we have our app up and running, we need to configure the web server properly. Right now it is in a very basic configuration with no multi-threading or logging.
Let’s go ahead and write our configuration in conf/gunicorn_config.py
import multiprocessing
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
accesslog = "-" # STDOUT
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
loglevel = "debug"
capture_output = True
enable_stdio_inheritance = True
bind — binds the web server to port 8000 and exposes it to all the interfaces
Workers — the number of worker threads serving the request
access-log and format — log to STDOUT in the given format.
Everything about this file is available in the docs.
Now with this web app and the server up and running, we want to containerize it into a Docker container. To do that, we have to write a Dockerfile.
Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. ~ Docker docs
Our Dockerfile looks like:
# python runtime
FROM python:3.6.5-alpine
# working directory
WORKDIR /app
# copy current directory into the container
ADD . /app
# install requirements
RUN pip3 install -r src/requirements.txt
# make port 8000 available to the world outside
EXPOSE 8000
CMD ["gunicorn", "--config", "./conf/gunicorn_conf.py", "src:app"]
We’ll go line by line and study this Dockerfile!
line 1: FROM allows us to initialize the build over a base image. In our case, we are using a python:3.6.5-alpine image. Alpine is a small Linux Distribution (~ 5MB). It is heavily used by Docker apps because of its small size. In short, we are using a Linux environment with python 3.6.5 for our app.
line 3: We create a WORKDIR called app where the pwd will be set.
line 8: Copy everything in the current directory (our server code and configurations) into the app directory.
line 11: Install the dependencies.
line 14: This exposes our container’s port 8000 for inter-container communication. We’ll later connect this port to the host machine to serve our web app on it.
line 16: The final command passed as a list of tokens. It runs the Gunicorn server with the config file.
Now we have a Dockerfile and all we need to build an image. After this, we’ll be able to run our image and see the web app in action!
Our source code should now look like the picture. Note that Dockerfile is outside the src folder.
We need to create a docker image and run it!
$ docker build -t helloworld
$ docker run -p 80:8000 helloworld
docker build creates an image from the Dockerfile and -t gives a tag to our image.
docker run takes in the tag argument to run the image and -p publishes the container’s port to the host.
So, our web app is now available at port 80.
Curl the localhost to see the app up and running!
Curl the localhost to see the app up and running!
We can list the active containers using docker ps
Everything about the active container!
Note how a random name is assigned to our container! For details, see thisgo file!
Now that we have a docker image and our very own app residing in it. What do we want to do now? How to make this image available to our AWS EC2 instance or some Linux cloud server?
We will push our image to a public registry on Docker Hub from where we will be able to pull it from later. To do so:
Create an account on Docker Hub and create a new repository! Below is the screenshot showing how to create a new repository!
Next, we need to tag our image on the command line and push it.
$ docker login
$ docker tag helloworld <username>/<repository-name>
$ docker push <username>/<repository-name>
Now this image can be pulled from anywhere using docker pull
On any Linux server,
$ docker run <username>/<repository-name>
Docker automatically pulls the image from Docker Hub and runs the instance!
This way, a docker image can be deployed anywhere.
We saw how to containerize our applications and host it anywhere using the Docker environment. For more on Dockers, read the official documentation and get your hands dirty with the containers.
Leave a Reply
Your email address will not be published. Required fields are marked *