Building Docker-Compose based MicroServices for a Flask Application

In this tutorial you will learn how to run a Flask Based Application with nginx as a microservice using Docker and Docker Compose.

Setup

Please install the following components before starting the lab

  • docker (1.6.0 or above)
  • docker-compose (1.3.1) or above

Test out the installs:

$ docker --version
Docker version 1.6.2, build 7c8fca2
$ docker-compose --version
docker-compose 1.3.1

Clone the Project

Next clone the project from the repo or create your own project based on the project structure found on the repo:

├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── sites-enabled
│       └── flask_project
└── web
    ├── Dockerfile
    ├── app.py
    ├── config.py
    ├── create_db.py
    ├── models.py
    ├── requirements.txt
    ├── static
    │   ├── css
    │   │   ├── bootstrap.min.css
    │   │   └── main.css
    │   ├── img
    │   └── js
    │       ├── bootstrap.min.js
    │       └── main.js
    └── templates
        ├── _base.html
        └── index.html

Docker Compose

Four Services are defined – web, nginx, postgres, and data.

../_images/nginx_flask_postgres_diagram1.png
  • web : The web service is built using the instructions in the Dockerfile within the “web” directory – where the Python environment is setup, requirements are installed, and the Flask app is fired up on port 8000. That port is then forwarded to port 80 on the host environment. This service also adds environment variables to the container that are defined in the .env file.
  • nginx : The nginx service is used for reverse proxy to forward requests either to the Flask app or the static files. It refers to the volumne of the web service
  • postgres : The postgres service is built from the the official PostgreSQL image from Docker Hub, which install Postgres and runs the server on the default port 5432.
  • data : There is a separate volume container that’s used to store the database data. This helps ensure that the data persists even if the Postgres container is completely destroyed.

Refer to the docker-compose.yml file:

web:
  restart: always
  build: ./web
  expose:
    - "8000"
  links:
    - postgres:postgres
  volumes:
    - /usr/src/app/static
  env_file: .env
  command: /usr/local/bin/gunicorn -w 2 -b :8000 app:app

nginx:
  restart: always
  build: ./nginx/
  ports:
    - "80:80"
  volumes:
    - /www/static
  volumes_from:
    - web
  links:
    - web:web

data:
  restart: always
  image: postgres:latest
  volumes:
    - /var/lib/postgresql
  command: true

postgres:
  restart: always
  image: postgres:latest
  volumes_from:
    - data
  ports:
    - "5432:5432"

Build Images

Now, to get the containers running, build the images and then start the services:

$ docker-compose build

Start all the containers

$ docker-compose up -d

Output to this command will show all the four containers coming up

Creating orchestratingdocker_data_1...
Creating orchestratingdocker_postgres_1...
Creating orchestratingdocker_web_1...
Creating orchestratingdocker_nginx_1...

Warning

Everytime you run this command a new set of containers will get launched

Connect to PostgreSQL

You can also enter the Postgres Shell – since we forward the port to the host environment in the docker-compose.yml file – to add users/roles as well as databases via:

$ psql -h 127.0.0.1 -p 5432 -U postgres --password

Default password is postgres

Once you are connected, you will notice there are no tables in the database

postgres=# \dt
No relations found.

Create Database Table

We also need to create the database table:

$ docker-compose run web /usr/local/bin/python create_db.py

Once connected to the DB you can run the following command to see the table created

postgres=# \dt
         List of relations
 Schema | Name  | Type  |  Owner
--------+-------+-------+----------
 public | posts | table | postgres
(1 row)

Open your browser and navigate to the IP address associated with Localhost (127.0.0.1):

../_images/screen_shot_1.png

When the posts are made, data gets persisted as shown below

postgres=# select * from posts;
 id |   text   |        date_posted
----+----------+---------------------------
  1 | Hi There | 2015-07-07 07:12:23.39434

Environment Variables

To see which environment variables are available to the web service, run:

$ docker-compose run web env

Logs

To view the logs:

$ docker-compose logs

logs from all the containers are aggregated and shown.

Stopping All Services

To stop the processes using following command

$ docker-compose stop.