I just didn’t find the time to look at docker-compose for real. I really was busy.
docker-compose is the replacement for the old project fig, which is now deprecated.
Kinda liked the name fig. But that’s perhaps because I love to eat some dried figs, especially before a run.
docker-compose helps you orchestrate your containers. Which means you can define your application environment with one simple YAML file.
Afterwards you are able to start up all necessary containers of the environment, i.e web containers, loadbalancer, proxies and database with one shell command:
You can find a lot of beginner tutorials on how to use docker-compose. This is why I wanted to try out a bit more than just starting an app and database container and linking them together.
example environment with loadbalancer
My idea was to startup this environment with docker-compose
We are going to use the tutum/haproxy image for the loadbalancer and the redis image for the database.
For the other components, I’m gonna create a nginx proxy and a flask web app.
installation of docker-compose
Docker-compose isn’t part of the docker package. So you will need to install it separately.
There are many ways to install it, including a curl-way. But I prefer
First we will need to create a project directory. Let’s just call it example
In this directory we will create a directory for each of our custom containers we are going to build, which are the nginx and flask. To simplify things, I’ll call the flask web app directory just app.
nginx container
We will use j2cli to create a nginx configuration from a template.
The syntax is jinja2. This will make it very easy to dynamically set the loadbalancer address and port as a proxy.
Our container can get this information from the environment variables which are set upon linking it to the haproxy.
Don’t bother mentioning that I defined localhost as servername. It’s obvious that you have to set it to your prefered one.
Why redirect the logs to /proc/self/fd/{1,2} you ask? Thanks to this we can see our logs with docker logs.
Now we create our Dockerfile and start script.
We could now build the docker image, but we will leave that to docker-compose.
flask app container
Let’s concentrate on our flask web app now.
The objective is to have a simple index page showing data from the database, i.e a visit counter.
To test our loadbalancer I want to return the hostname too.
Here is the code I’m using. I saved it under ~/example/app/app.py.
I’m using the environment variables REDIS_PORT_6379_TCP_ADDR and REDIS_PORT_6379_TCP_PORT to connect to the redis database.
This environment variables will be available thanks to linking the container to the redis database.
Now let’s create a Dockerfile for our web app too.
docker-compose.yml
We are nearly there. We just need to create our pretty YAML file as a definition for our “container orchestra”.
We are defining the components in a really simple way. The build options tells docker-compose in which directory it can switch to build the container image.
image is used to take an already existing image.
links is one of the most exciting options. Not only it tells our containers with which other components it is linked to, it also creates a dependency-relationship between them. It makes sure your containers will start in the right order.
Our app is listening to port 5000, that’s why I’m passing BACKEND_PORT as environment variable to the haproxy. It will now forward requests to the right port.
Finally, I want to test the app over our nginx. That’s why I’m mapping 80:80 with the help of ports
docker-compose up?
No, not yet. There is something else we have to do.
With this configuration docker-compose would only start one single web app container. But we want to start three. This is where docker-compose scale comes in handy.
It builds the container image and creates 3 containers. But is it starting them up already?
We can look that up with docker. The answer is yes, but no. It simply stopped them afterwards.
what about docker-compose up now?
Yes. Now is the time to finally bring the environment up.
We could have used docker-compose up -d to not see all this noise. These logs are always available over docker-compose logs.
What does docker ps tells us now?
It brought up our redis database, haproxy and nginx container. It also created 3 new containers for the web app, app_3,app_4 and app_5.
Docker-compose itself has a handy ps argument too.
testing
Does the haproxy really work?
Is it balancing requests with the round robin algorithm?
Is our nginx proxy doing his job?
Will the redis database be reachable from our flask app?
So many questions, so let’s just try it out!
YAY IT WORKS
summary
Docker-compose can help us define a whole container orchestration in one single file. We don’t need anymore to start up containers in the right order and link them, docker-compose takes care of it now.
There is way more to know about it though. It comes with many options and arguments I haven’t yet read about.
But in hope I will find more time in future, I’m looking forward to try them out.