top

Getting started with Flask on Docker

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 docsThat is why we use a WSGI server. Gunicorn is simple and reliable.So, what is Docker?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.SetupCreate 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-appWriting the web appWe 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 instancerequirements.txt  — to list out the modules required from flask import Flask app = Flask(__name__) from .server import *flask gunicorn Move 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! Configuring the Gunicorn serverNow 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.pyimport 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 = Truebind — binds the web server to port 8000 and exposes it to all the interfacesWorkers — the number of worker threads serving the requestaccess-log and format — log to STDOUT in the given format.Everything about this file is available in the docs.Dockerizing!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 docsOur 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.All set to runNow 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 helloworlddocker 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!Deploying it!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?DOCKER HUB!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 pullExample: Docker on Linux BoxOn 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. Conclusion: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. 
Rated 4.0/5 based on 32 customer reviews
Normal Mode Dark Mode

Getting started with Flask on Docker

Shubham Sharma
Blog
14th Jul, 2018
Getting started with Flask on Docker

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.


So, what is Docker?

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                   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.


Setup

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


Writing the web 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

  • requirements.txt — to list out the modules required

    from flask import Flask
    
    
    app = Flask(__name__)
    
    
    from .server import *
    flask
    
    gunicorn
    
    
    Move all the code in the ‘src’ folder and the file tree should look like that in the figure.

 web app

 Let’s quickly fire up the terminal and test this server!


$ pip3 install -r src/requirements.txt
$ gunicorn src:app

serving hello-world!

                                                                                        ‘/’ serving hello-world! 


Configuring the Gunicorn server

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.


Dockerizing!

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.


All set to run

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! 

All set to run

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! 

Curl the localhost to see the app up and running!


We can list the active containers using docker ps 

Everything about the active container!                                                                                Everything about the active container! 

Note how a random name is assigned to our container! For details, see thisgo file!


Deploying it!

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?


DOCKER HUB!

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


Example: Docker on Linux Box

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. 


Conclusion:

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. 


Shubham

Shubham Sharma

Blog Author

I am a computer science undergrad. I like writing about technology and learning new things every day. Besides computers, I also like playing music. I play the guitar occasionally. I prefer tabs over spaces.

Leave a Reply

Your email address will not be published. Required fields are marked *

SUBSCRIBE OUR BLOG

Follow Us On

Share on

other Blogs

20% Discount