Using Docker Compose
"Compose is a tool for defining and running multi-container applications with Docker.
With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running." (from Overview of Docker Compose)
With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running." (from Overview of Docker Compose)
Simple three steps to use Docker Compose.
- Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
- Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
- Lastly, run docker-compose up and Compose will start and run your entire app.
In this Chapter, we are going to learn how to use Docker Compose with the simple application shown below.
5-1. Let's create simple Docker Compose
- Make a directory with the name "compose" under ~workspace/docker
$ mkdir -p ~/workspace/docker/compose
$ cd ~/workspace/docker/compose
- Create an application
$ vi app.py
from flask import Flask from redis import Redis import os app = Flask(__name__) redis = Redis(host='redis', port=6379) @app.route('/') def hello(): redis.incr('counter') return'Hi! You saw me %s times.'% redis.get('counter') if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
This application increments the counter in redis each time you access it with web browser. - Create requirements file
$ vi requirements.txt
flask redis
- Create Dockerfile
$ vi Dockerfile
FROM python:2.7 ADD . /code WORKDIR /code RUN pip install -r requirements.txt
- Create docker-compose.yml
$ vi docker-compose.yml
web: build: . command: python app.py ports: - "5000:5000" volumes: - .:/code links: - redis redis: image: redis
In this example, we define the Multi-Container application which has "web" and "redis" containers in compose. - Start the Multi-Container Application
$ docker-compose up -d
[AKIRA@^_^:compose]$ docker-compose up -d Pulling redis (redis:latest)... latest: Pulling from library/redis ba249489d0b6: Pull complete : Status: Downloaded newer image for redis:latest Creating compose_redis_1... : Building web... Step 0 : FROM python:2.7 2.7: Pulling from library/python 843e2bded498: Pull complete 8c00acfb0175: Pull complete : Successfully built 1622bc6ab5bb Creating compose_web_1...
- Check the running containers
$ docker-compose ps
[AKIRA@^_^:compose]$ docker-compose ps Name Command State Ports compose_redis_1 /entrypoint.sh redis-server Up 6379/tcp compose_web_1 python app.py Up 0.0.0.0:5000->5000/tcp
We can see that 2 containers are started by Docker Compose.
The port 5000 of compose_web_1 container is bound to the port 5000 of Docker Host (vm-appcat01). - Check the IP Address of vm-appcat01
[AKIRA@^_^:dockerfiles]$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM vm-appcat01 * vmwareappcatalyst Running tcp://172.16.194.154:2376
- Access the application with the browser.
172.16.194.154:5000
- Access again, and the counter gets incremented by 1.
(The counter on redis got incremented) - Edit your application
$ vi app.py
return'Hey Dude, You saw me %s times.'% redis.get('counter')
From "Hi" to "Hey Dude" - Access your applicationYour Web application is updated (Hi -> Hey Dude)
redis counter gets incremented (counter = 3) - Display logs
$ docker-compose logs
[AKIRA@^_^:compose]$ docker-compose logs Attaching to compose_web_1, compose_redis_1 web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) :
- Stop the containers
$ docker-compose stop
[AKIRA@^_^:compose]$ docker-compose stop Stopping compose_web_1... done Stopping compose_redis_1... done
- Access your application with Web browser.(App is down)
- Restart your containers
$ docker-compose up -d
[AKIRA@^_^:compose]$ docker-compose up -d Starting compose_redis_1... Starting compose_web_1...
- Access your application
redis counter is kept and incremented even after restart. (counter = 4) - Stop the containers
$ docker-compose stop
- Remove the containers
$ docker-compose rm
Both web and redis containers are removed.
5-2. Scaling out your app
Let's scale out your web application with docker-compose.
- Edit docker-compose.yml
$ vi docker-compose.yml
web: build: . command: python app.py ports: - "5000" volumes: - .:/code links: - redis redis: image: redis
In the first example, we bind port 5000 of docker host to port 5000 of web container. (- "5000:5000"
)
This prevents us from scaling out the web container because the port 5000 on docker host would be in use by the first web container.
So this time we set this as- "5000"
.
This will bind the port 5000 of "web" container to arbitrary port of docker host. - Start the containers with Docker Compose
$ docker-compose up -d
[AKIRA@^_^:compose]$ docker-compose up -d Creating compose_redis_1... Building web...
- Check the running containers
$ docker-compose ps
[AKIRA@^_^:compose]$ docker-compose ps Name Command State Ports compose_redis_1 /entrypoint.sh redis-server Up 6379/tcp compose_web_1 python app.py Up 0.0.0.0:32768->5000/tcp
Note the port number of compose_web_1.
Port 5000 of container is bound to 32768 of the Docker Host (vm-appcat01). - Check the IP Address of Docker Host (vm-appcat01)
$ docker-machine ip vm-appcat01
[AKIRA@^_^:compose]$ docker-machine ip vm-appcat01 172.16.194.161
You can usedocker-machine ls
, too. - Now, we scale out the web container by 1 (make it 2)
$ docker-compose scale web=2
[AKIRA@^_^:compose]$ docker-compose scale web=2 Creating and starting 2... done
- Check the running containers
$ docker-compose ps
[AKIRA@^_^:compose]$ docker-compose ps Name Command State Ports compose_redis_1 /entrypoint.sh redis-server Up 6379/tcp compose_web_1 python app.py Up 0.0.0.0:32768->5000/tcp compose_web_2 python app.py Up 0.0.0.0:32769->5000/tcp
You can see there are two "web" containers running. - Let's make it 10!
$ docker-compose scale web=10
[AKIRA@^_^:compose]$ docker-compose scale web=10 Creating and starting 3... done Creating and starting 4... done Creating and starting 5... done Creating and starting 6... done Creating and starting 7... done Creating and starting 8... done Creating and starting 9... done Creating and starting 10... done
Now you have 10 web containers running. - Check it out.
$ docker-compose ps
[AKIRA@^_^:compose]$ docker-compose ps Name Command State Ports compose_redis_1 /entrypoint.sh redis-server Up 6379/tcp compose_web_1 python app.py Up 0.0.0.0:32769->5000/tcp compose_web_10 python app.py Up 0.0.0.0:32770->5000/tcp compose_web_2 python app.py Up 0.0.0.0:32768->5000/tcp compose_web_3 python app.py Up 0.0.0.0:32774->5000/tcp compose_web_4 python app.py Up 0.0.0.0:32773->5000/tcp compose_web_5 python app.py Up 0.0.0.0:32777->5000/tcp compose_web_6 python app.py Up 0.0.0.0:32771->5000/tcp compose_web_7 python app.py Up 0.0.0.0:32772->5000/tcp compose_web_8 python app.py Up 0.0.0.0:32775->5000/tcp compose_web_9 python app.py Up 0.0.0.0:32776->5000/tcp
- Now we make "web" containers to 3 and redis to 2.
$ docker-compose scale web=3 redis=2
[AKIRA@^_^:compose]$ docker-compose scale web=3 redis=2 Stopping compose_web_4... done Stopping compose_web_5... done Stopping compose_web_6... done Stopping compose_web_7... done Stopping compose_web_8... done Stopping compose_web_9... done Stopping compose_web_10... done Removing compose_web_10... done Removing compose_web_6... done Removing compose_web_5... done Removing compose_web_8... done Removing compose_web_7... done Removing compose_web_4... done Removing compose_web_9... done Creating and starting 2... done
- Check it.
$ docker-compose ps
[AKIRA@^_^:compose]$ docker-compose ps Name Command State Ports compose_redis_1 /entrypoint.sh redis-server Up 6379/tcp compose_redis_2 /entrypoint.sh redis-server Up 6379/tcp compose_web_1 python app.py Up 0.0.0.0:32769->5000/tcp compose_web_2 python app.py Up 0.0.0.0:32768->5000/tcp compose_web_3 python app.py Up 0.0.0.0:32774->5000/tcp
Now we know that we can scale-in and out ”web" and "redis" independently. That's really good. - Stop the containers
$ docker-compose stop
[AKIRA@^_^:compose_]$ docker-compose stop Stopping compose_redis_2... done Stopping compose_web_3... done Stopping compose_web_2... done Stopping compose_web_1... done Stopping compose_redis_1... done
- Remove the containers
$ docker-compose rm
[AKIRA@^_^:compose]$ docker-compose rm Going to remove compose_redis_2, compose_web_3, compose_web_2, compose_web_1, compose_redis_1 Are you sure? [yN] y Removing compose_redis_2... done Removing compose_web_3... done Removing compose_web_2... done Removing compose_web_1... done Removing compose_redis_1... done
No comments: