Day: January 11, 2022

Docker Compose – Flask/Redis sample

Docker Compose - Flask/Redis sample

Files

app.py

from flask import Flask, request, jsonify
from redis import Redis

app = Flask(__name__)
redis = Redis(host="redis", db=0, socket_timeout=5, charset="utf-8", decode_responses=True)

@app.route('/', methods=['POST', 'GET'])
def index():

    if request.method == 'POST':
        name = request.json['name']
        redis.rpush('students', {'name': name})
        return jsonify({'name': name})

    if request.method == 'GET':
        return jsonify(redis.lrange('students', 0, -1))

Dockerfile

FROM python:3.7.0-alpine3.8

WORKDIR /usr/src/app

COPY requirements.txt ./

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENV FLASK_APP=app.py

CMD flask run --host=0.0.0.0

Build

docker-compose build

Network

docker network ls

This will show a network named as flash-redis_default created, which used by both flash and redis containers. The containers can use service name to communicate to each other.

Use parameters and arguments

Create a file called .env

PYTHON_VERSION=3.7.0-alpine3.8
REDIS_VERSION=4.0.11-alpine
DOCKER_USER=takacsmark

In docker-compose.yml file, replace environment session with env_file: .env.txt session, then use environment variable to define argument

version: "3"

services:
  app:
    build:
      context: .
      args:
        - IMAGE_VERSION=${PYTHON_VERSION}
    image: ${DOCKER_USER}/flask-redis:1.0
    env_file: .env.txt
    ports:
      - 80:5000
    networks:
      - mynet
  redis:
    image: redis:${REDIS_VERSION}
    networks:
      - mynet
    volumes:
      - mydata:/data

networks:
  mynet:
volumes:
  mydata:

In Dockerfile use argument from docker-compose.yml file

ARG IMAGE_VERSION

FROM python:$IMAGE_VERSION

WORKDIR /usr/src/app

COPY requirements.txt ./

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENV FLASK_APP=app.py

CMD flask run --host=0.0.0.0

docker and docker-compose commands

docker-compose ps
docker-compose logs
docker-compose logs -f app
docker-compose stop
docker-compose start
docker-compose restart
docker-compose kill
docker-compose top

exec

docker-compose exec redis redis-cli lrange students 0 -1
docker-compose exec app /bin/bash

run

Start a new container, but port mapping will not be applied for new container by default.

docker-compose run ls -al

Desired state

Docker compose is defining the desired state, which will update the existing containers after configuration changed if possible.

For example, update port in doctor-compose.yml file, once run docker-compose up -d again, only app server will be recreated.

Note: Don't need to destroy existing containers first before run up again.

Scale

docker-compose up --scale app=3

Note: If ports session defined, there will be conflicting of port map.

Network

In docker-compose.yml file

services:
  app:
      networks:
      - mynet

networks:
  mynet:

Then a network called <project_name>_mynet will be created.

The old network can be pruned

docker network prune

External network

Network can be defined outside of docker-compose.yml file, which indicated as external network

networks:
  outside:
    external:
      name: actual-name-of-network

volumes

docker volumes ls

In docker-compose.yml file

services:
  redis:
    volumes:
      - mydata:/data

volumes:
  mydata:

Then a volume called <project_name>_mydata will be created.

Configuration Override

Single override file

The options in docker-compose.override.yml will overwrite or extend options in docker-compose.yml.

Note: Array options will be extended.

Multiple override files

docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.dev.yml up -d

Migrate to cloud

Push images to docker hub

docker-compose push

Pull and run in play with docker (PWD)

docker-compose pull
docker-compose up -d

Sample data

Add sample data into redis

curl --header "Content-Type: application/json" \
--request POST \
--data '{"name":"Bruno"}' \
http://ipxxxxxxxxx.direct.labs.play-with-docker.com/

To access the sample data

curl http://ipxxxxxxxxx.direct.labs.play-with-docker.com/

Compose file reference

https://docs.docker.com/compose/compose-file/

Note: some options are only working in swarm mode or compose mode. For example, deploy only works in swarm mode, build only works in compose mode.

References

Docker compose tutorial for beginners by example [all you need to know] (Video)
Docker compose tutorial for beginners by example [all you need to know]