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)
- Go to https://labs.play-with-docker.com/
- Add a new instance.
- Drag and drop
docker-compose.yml
file into the new session - Run docker-compose
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]