I've been working on a few projects at the moment and scaling keeps coming to a head. So let's take a look on how to scale a Docker web services stack with Docker-Compose. Before we get started we need to lay a bit of ground work.
What we are building is a web service with three components that are built, configured, and deployed via docker-compose.
- HAProxy which provides us with round-robin load balancing
- Web Application based on Python
- Redis Database
The HAProxy receives the web requests and routes it to the single web service which prints the hostname of the container that receives the request where a counter is incremented, and this value is then stored in the Redis Database.
Now let's scale our stack out to 5 web instances/containers that are now load balanced and still connected to the Redis DB. Docker-compose easily scales our service from 1 to 5 instances. Once the web services scales out to 5 we need to inform the Database and HAProxy of these changes so they can accept and route traffic accordingly.
As before the web requests are received by the HAProxy but are now routed round-robin to all 5 of the web service instances. All these instances are also linked to the Redis DB and thus our application prints the hostname and increments the number of visits works flawlessly all while printing the hostname from each container that responds. We can also scale the the web service back to 1 container when we are done.
DEMO - How to scale Docker Containers with Docker-Compose
You can find the contents of this demo on my Github/vegasbrianc page
In order to get started be sure to clone this project onto your Docker Host. Create a directory on your host. Please note that the web services will inherit the name from the directory you create. If you create a folder named test. Then the services will all be named test-web, test-redis, test-lb. Also, when you scale your services it will then tack on a number to the end of the service you scale.
git clone https://github.com/vegasbrianc/docker-compose-demo.git .
How to get up and running
Once you've cloned the project to your host we can now start our demo project. Easy! Navigate to the directory in which you cloned the project. Run the following commands from this directory
docker-compose up -d
The docker-compose command will pull the images from Docker Hub and then link them together based on the information inside the docker-compose.yml file. This will create ports, links between containers, and configure applications as required. After the command completes we can now view the status of our stack
Verify our service is running by either curlng the IP from the command line or view the IP from a web browser. You will notice that the each time you run the command the number of times seen is stored in the Redis Database which increments. The hostname is also reported.
Curling from the command line
curl 0.0.0.0 Hello World! I have been seen 1 times. My Host name is 29c69c89417c
Now comes the fun part of compose which is scaling. Let's scale our web service from 1 instance to 5 instances.
docker-compose scale web=5
We have now scaled our web service container. We now should run an update on our stack so the Load balancer and Redis are informed about the new web service containers.
Now run our curl command again on our web services and we will now see the number of visits increase and the hostname change. To get a deeper understanding tail the logs of the stack to watch what happens each time you access your web services with curl.
Here's the output from my docker-compose logs after I curled my application 5 times so it is clear that the round-robin is sent to all 5 web service containers.
web_5 | 172.17.1.140 - - [04/Sep/2015 14:11:34] "GET / HTTP/1.1" 200 - web_1 | 172.17.1.140 - - [04/Sep/2015 14:11:43] "GET / HTTP/1.1" 200 - web_2 | 172.17.1.140 - - [04/Sep/2015 14:11:46] "GET / HTTP/1.1" 200 - web_3 | 172.17.1.140 - - [04/Sep/2015 14:11:48] "GET / HTTP/1.1" 200 - web_4 | 172.17.1.140 - - [04/Sep/2015 14:14:19] "GET / HTTP/1.1" 200 -
The docker-compose project has been updated. The main docker-compose.yml file is in version2 format and version 1 file is no longer maintained. A downside of moving to version 2 is my CircleCI no longer performs automated testing as CircleCI amazingly doesn't support version 2 files yet. Booo!