Developing Flask App Locally with Docker: Part II

Arash Soheili
Published January 14, 2017

In part I of this tutorial we talk about how to setup our Dockerfile. These are instructions for setting up our server and installing the required libraries and application code. In this part we're going to discuss Docker Compose and how to coordinate container.

Docker Compose is a separate application form Docker and must be installed. But what is Docker Compose and why do we need it? In a typical production environment you might have you application on a server and your database on another server. In addition your may have other services or micr-services running on other servers. How do we setup that up with Docker containers? We can bring up several containers and then link them together using Docker. But this becomes tedious to do every time and not reproducible. Therefore, we have Docker Compose that let's us do just that with a set of instructions.

Docker Compose is a command line tool that can be invoked using the command docker-compose. All you need to start is a yaml file called docker-compose.yml. Let's take a look at an example file.

version: '2'
services:
  web:
    build: .
    ports:
      - "8000:80"
    volumes:
      - .:/home/ubuntu/python-blog
    environment:
        - PYBLOG_ENV=Docker
    container_name: blog_web
    links:
        - db
  db:
    image: mysql:5.7
    ports:
      - "3308:3306"
    environment:
        - MYSQL_RANDOM_ROOT_PASSWORD=yes
    container_name: blog_db

In this example we are setting up a web server and a database server and linking them together. Let's take a closer look and analyze the document.

version: '2'

Docker Compose has two formats for their compose file. We are using version 2 which is the latest. You can get more details on the formats and references here.

services:

Services are the important part and are the containers that we are going to setup. You can name the services anything you want. In this example we have a web service which is where we'll have our application. We also have a db services which will be our mysql database. Let's take a look at how these services or containers are built.

web:
  build: .

Services can be built using a local Dockerfile or a hosted images. In this example the web services is being built using the local Dockerfile. The build . means to look for a Dockerfile in the current directory. If you file is not in the current directory or has a different name then you'll need to use the syntax below.

web:
  build:
    context: ./dir
    dockerfile: Dockerfile-alternate
db:
  image: mysql:5.7

Services can also be built using hosted images. Here we are using the open source mysql container with tag 5.7 for our desired version. You can also use your own hosted images that is either public or private. If you image is private you will need to make to login previously using the docker login command.

ports:
    - "8000:80"

In order to access our app on our host machine we'll need to map a port on our host machine to our container. This is easily done using the ports section of the docker compose file. Here we mapping our host port 8000 to the container port 80. After it's all setup we'll be able to visit localhost:8000 on our host machine which should display our app.

volumes:
    - .:/home/ubuntu/python-blog

As we're developing locally we'll be making changes to files on our host machine and we'll want this to be reflected in our container. The volumes section does just that by syncing our host files to the container files. In this example we are syncing our current repo directory to the container /home/ubuntu/python-blog.

environment:
    - PYBLOG_ENV=Docker

If the setup of your app required environment variables then you pass them to your container using the environment section. You can pass as many as your need and even reference your host machine environment variables.

links:
    - db

Now one of the most important sections and the reason we are using Docker Compose is the links section. Here we are going to link the web services to the db services. This then allows us to reference the database container in our web container using the name db. This is equivalent to the url of the database server.

Once your docker compose file is ready then you can start everything by using the command docker-compose up. This will build all the services and bring up the container. You can take down the container using docker-compose down. It's that easy.

In this example we only setup a web container and a db container having them linked. But you can setup as many services as you need and link them together. For example, if your app uses redis-server or memcache then you can add that as another service and link it to your web service.

As you can see Docker Compose is a powerful way to setup your application environment in a reproducible way. It will help you to develop locally with confidence knowing that things will work in production. It's also a great way to test changes to your application before going to production. If you have question or want to reach me then contact me on Twitter.