Multi tier apps in Docker.io

13Jan14

Docker provides the means to link containers, which comes in two parts:

  1. Outside the container (on the docker command line) a ‘-link name:ref’ is used to create a link to a named container.
  2. Inside the container environment variables REF_… are populated with IP addresses and ports.

Having linked containers together it’s then necessary to have a little plumbing inside the containers to get the contents of those environment variables to the right place.

My example application

A while ago a saw a demo of Apcera, which used a little ToDo list application as a means to show off the capabilities of the platform. I thought a similar demo would be useful for CohesiveFT’s VNS3[1], and I found a suitable basis with theponti‘s sinatra-ToDoMVC app. My version of the app has been modified to use MySQL as a back end, and I also add Nginx as a front end to make a 3 tier demo.

If you want to just dive in

I’ve put my app into github, and it’s available as a trusted build from my page on the Docker public index. To just run it up start each tier in turn:

# first create the directory for persistent data:
sudo mkdir -p /data/mysql

# start the database
sudo docker run -d -p 3306:3306 -name todomvc_db \
-v /data/mysql:/var/lib/mysql cpswan/todomvc.mysql

# start the app server
sudo docker run -d -p 4567:4567 -name todomvc_app \
-link todomvc_db:db cpswan/todomvc.sinatra

# start the web server
sudo docker run -d -p 443:443 -name todomvc_ssl \
-link todomvc_app:app cpswan/todomvc.ssl

The database

The MySQL database is the base dependency, so nothing happening here in terms of linking.  I’ve adapted Ben Schwartz’s scripts for creating a MySQL Docker container to add in the creation of the ToDoMVC database.

The only other noteworthy thing happening here is the externalisation of the MySQL database storage back to the host machine using the -v flag.

The app server

This is linked back to the database with ‘-link todomvc_db:db’. Inside the container this gives various environment variables starting DB_. The appropriate one is parsed into the database URL within the Sinatra application using the following couple of lines of Ruby:

dburl = 'mysql://root:pa55Word@' + ENV['DB_PORT_3306_TCP_ADDR'] + '/todomvc'
DataMapper.setup(:default, dburl)

Note that the Dockerfile for the app server is grabbing the Ruby code straight from the docker branch of my fork of the sinatra-ToDoMVC application. If you want to see that database URL in context then take a look at the source for app.rb. The credentials being used here are what was set back in the database start script.

The web server

This is linked back to the app server with ‘-link todomvc_app:app’.  Inside the container this gives various environment variables starting APP_. As Nginx can’t do anything useful with those variables it’s necessary to parse them into nginx.conf before starting the server, which is what the start_nginx.sh script is there to do:

#!/bin/bash
cd /etc/nginx
cp nginx.conf.template nginx.conf
eval "echo \"`cat upstream.template`\"" >> nginx.conf
service nginx start

The nginx.conf has been split into two templates. For the bulk of it (nginx.conf.template) there’s no need to environment substitution, in fact doing so will strip out env variables that need to be there. Only the upstream section is required so that:

upstream appserver {
    server $APP_PORT_4567_TCP_ADDR:$APP_PORT_4567_TCP_PORT;
  }
}

Gets turned into something like:

upstream appserver {
    server 172.17.0.62:4567;
  }
}

The trailing brace is there to complete the unfinished http section from the main nginx.conf.template.

That’s it :)

Browsing to https://docker_host/todos should get the todo list up.

Note

[1] For my demo with VNS3 I spread the tiers of the app across multiple clouds – almost the exact opposite of what’s happening here with all three tiers on the same host. In that case VNS3 provides the linking mechanism via a cloud overlay network – so there’s no need to tinker with the application config to make it aware of it’s environment – hard coded IPs are fine (even if they’re generally a config antipattern).



3 Responses to “Multi tier apps in Docker.io”

  1. Hi Chris!

    thanks for sharing your docker experiences. i’ve been playing with it for a couple of months already but didn’t have the right amount of time necessary to write about it eheh
    on the webserver part, instead of that cucumbersome setup, give a try to crosbymichael skydock (service discovery dns-based)! https://github.com/crosbymichael/skydock

    Cheers,
    Tiago.


  1. 1 Multi tier Docker apps with Fig | Chris Swan's Weblog
  2. 2 Fun with Flocker | Chris Swan's Weblog

Leave a reply to tpires Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.