Docker compose

Containers are by default isolated from each other. Docker compose is used to enable communication between different containers

Wraps docker build and run commands. It is useful when we have a long run command and we dont want to execute it everytime.

It can also run multiple containers

Illustraion

Consider the following usecase:

We want a flask app and django app running in different containers in same host machine

We also want a redis server that counts the visitors to both the applications

docker-compose.yml

version: '3'
services: #List of all images
   redis-server:
      image: 'redis' #image in docker hub
   flask1:
      build: flask1/ #location of Dockerfile corresponding to flask1
      ports:
         - "4000:8000"
   flask2:
      build: flask2/ #location of Dockerfile corresponding to flask2
      ports:
         - "4001:8000"

flask1/Dockerfile (for simplicity, the other dockerfile also looks same)

FROM python:3.7.1-alpine3.7
RUN pip install flask==1.0.2
RUN pip install redis
WORKDIR /home
COPY ./ ./
CMD ["python","main.py"]

flask1/main.py

from flask import Flask
        import redis

        #Connecting to redis server
        r = redis.Redis(host='redis-server') 
        #hostname is the image name in docker-compose.yml
        #if the server is on different macine, this will be its ip address
        r.set('visits',0)

        app = Flask(__name__)
        app.debug=True

        @app.route('/')
        def index():
            v = r.get('visits')
            #increment visits
            r.set('visits',int(v)+1)
            #if the container is on different machine, this will be its ip address
            out = "<h1>Hi Flask1. <a href='http://localhost:4001'>Link To Flask2</a></h1>"
            out += "<p>Visits : " + str(int(v))  + "</p>"
            return out

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

We have a similar flask2/main.py that adds counts of visits to its app

Compile

To build the images and run

docker-compose up --build #from the folder conatining docker-compose.yml

Now you can see additional images for Dockerfiles in cache with default tag docker compose [SERVICE_NAME]

To only run the built image

docker-compose up

More commands

Launch in background

docker-compose up -d

Stop containers

docker-compose down

To see status of all containers running corresponding to a docker-compose file

docker-compose ps #from directory containing docker-compose.yml

Restart policies

Often times, we want our server to automatically restart in case of failures. In those cases, we spicify the restart policy in docker-compose.yml

services: #List of all images
   flask1:
      build: flask1/ 
      restart: on-failure #if app stops with error code >0, it automatically restarts
      ports:
         - "4000:8000"

Policies:

"no" : (Default) Never restart

always : Always restart. Used for webservers that are always running

on-failure : Restart when there are common errors, like unable to write to file system

unless-stopped : Stop only when it is forced

Using different Dockerfile name

Lets say we name the dockerfile as Dockerfile.dev (commonly used convention for development code)

services:
    flask1:
       build:
         context: flask1/
         dockerfile: Dockerfile.dev

Specifying volumes

We specify volumns under volumes section

services:
    flask1:
       volumes:
         - /home/dep
         - .:/home #current dir mapped to /home
         - /home/sank/image_data:/data

Overriding start up command in docker file

Specify under command section

services:
   redis-server:
      image: redis
      stdin_open: true # -i (not working)
      tty: true # -t (not working)
      command: ["sh"]

Specifying build image name and container name

Specify the image option and container_name option

services:
   flask1:
      build: .
      image: flask1
      container_name: flask_container