This is “post 1” in a series of tutorials designed to stand up an Amazon ec2 instance which will provide the automated hosting of applications using docker. This first post starts with some base line provisioning and ends with a manual walk through of what we will automate in later posts.
If asked to characterize Docker (I know, no one has), I’d say that it’s a pattern/software that revolutionizes application and service deployment by reducing artifacts to a lowest common denominator, while at the same time making orchestration and discovery a pain in the ass. In this post (and others in the series if I get around to it) I’m going to attempt to play to docker’s strengths while automating the “pain in the ass” parts, to create a platform which will make hosting prototypes dirt simple. Why prototypes and not production applications? Because (right now at least) I don’t plan on addressing data persistence, scalability (beyond a single EC2 instance), or different environments like dev and uat. Don’t get me wrong, docker (and Hipache, which I’ll introduce later) is actually quite good at handling these concerns, but again… I don’t plan on addressing them.
I find it painful to describe how to use a gui (and acknowledge this to be irrational), and I’m sure you can figure out how to use Amazon, but in the interest of completeness and not assuming anything, I’m going to burn through this real quick.
You can now shell into your vm with something like the following:
ssh -i ~/.ssh/aws-key-benschw.pem ubuntu@54.244.120.37
I like to create myself an account separate from the ubuntu one too (so I don’t have to look up ssh’s -i
flag mostly). Just make sure to install your own ssh-key and add yourself to the sudoers group.
sudo su
adduser ben
usermod -G sudo ben
su ben
# paste your key into ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
I can’t improve upon Docker’s own install docs, so I won’t try. Follow their instructions (I copy pasted every line and hit “y” or “enter” a couple of times) from inside your EC2 instance.
Now lets install a copy of wordpress on port 80 just to confirm everything is right so far. Normally, we’d just let docker assign us a port, but for now lets ask for 80 since we’ve only punched a limited number of holes in our EC2 instance
sudo docker pull jbfink/wordpress
sudo docker run -d -p 80:80 jbfink/wordpress:latest
Navigate to your elastic IP and confirm the install screen comes up. Since it did, we’re all good to go and now it’s time to tear it down and reclaim our precious port 80.
sudo docker stop f26d90158382
If you forgot your id, sudo docker ps -a
should give you what you’re looking for.
(https://index.docker.io lists public containers if wordpress doesn’t get your motor going…)
Now it’s time to address our port problem. Lets face it, keeping track of them is a big part of the “pain in the ass” thing, and they don’t make for a very friendly user experience. If I was my dad (and if my dad was a sysadmin) I’d host everything on port 80 and assign ips to each docker container, but I’m not so I won’t.
Enter Hipache.
Hipache is a distributed proxy designed to route high volumes of http and websocket traffic to unusually large numbers of… take a look at the readme if you want a definition, but suffice it to say, it’s distributed, scalable, and solves our port problem.
Since we’re building a prototyping box, persistence isn’t too important. In fact, to keep things simple, let me just warn you now, that restarting your host machine is going to nuke (most of) everything we’re about to do.
That said, lets pull down a Hipache container from the Docker index and get ‘er running:
sudo docker pull samalba/hipache
sudo docker run -d -p 6379:6379 -p 80:80 samalba/hipache supervisord -n
# this spits out our Hipache container ID, in my case it's `e40c90158472`
sudo docker inspect e40c90158472 | grep Bridge | cut -d":" -f2 | cut -d'"' -f2
# probably better ways to parse JSON, but this will serve to get us our
# bridge interface; in my case it's `docker0`
/sbin/ifconfig docker0 | sed -n '2 p' | awk '{print $2}' | cut -d":" -f2
# more black magic to get our bridge's ip (which doubles as our redis
# host): for me it's 172.17.42.1
Recap: Hipache is running and we know some stuff about it. Since we specified port 80 & 6379, we also know Hipache is running on port 80 and redis is running on port 6379. (By the way, redis is a database and provides configuration for Hipache.)
Now we need somehow to find our containers since we want Hipache to get rid of ports; DNS should do the trick. In the interest of progressing towards our prototyping platform, I’m going to set up a wildcard record that points to our host IP. For me, I used *.io A 54.212.254.136
in my fliglio.com dns. (This way *.io.fliglio.com will point to my EC2 host machine.)
The last piece of prep work is to get a redis client installed on the host machine so we can configure Hipache.
sudo apt-get install redis-server
The downside of this, is we just installed the client and the server, and Ubuntu has started up a redis server on our host machine… go ahead and kill it:
sudo /etc/init.d/redis-server stop
Thats all there is to it, we’re ready to roll! …or maybe you’re thinking that was a lot of work and you’re ready to go back to ips…
Back to the ol’ wordpress standby. This time we aren’t going to specify a port, but are instead going to let Docker assign it an obnoxious random one.
sudo docker run -d -p 80 jbfink/wordpress:latest
sudo docker ps -a
will tell us the port mapping, or we can use the container id to find what got mapped to port 80.
sudo docker port d6077ac8b6e8 80
# 49154
The last step is to configure Hipache to route traffic sent to the domain we decided on (I’m using wp.io.fliglio.com) to the bridge ip our wordpress container is running on (the same as the one we figured out earlier for Hipache in this single host scenario) with the port docker is exposing the wordpress container’s port 80 through (49154)
redis-cli -h 172.17.42.1 -p 6379 rpush frontend:wp.io.fliglio.com wpdemo
redis-cli -h 172.17.42.1 -p 6379 rpush frontend:wp.io.fliglio.com http://172.17.42.1:49154
Thats it! wp.io.fliglio.com
should take you to a fresh wordpress installer that will generate even less traffic than this blog!
In Part 2, we’ll dive into automating some of this and leveraging it as a sandbox for prototyping. Granted most blogs end up being ephemeral anyway (without the help of Docker or this tutorial), but maybe we can squeeze a little more than wordpress installer hosting out of this setup just the same.
Spin up a second wordpress container, add a corresponding config entry to Hipache, and see how easy it is to get load balanced applications with Docker:
ID=$(sudo docker run -d -p 80 jbfink/wordpress:latest)
PORT=$(sudo docker port $ID 80)
redis-cli -h 172.17.42.1 -p 6379 rpush frontend:wp.io.fliglio.com http://172.17.42.1:$PORT
since i’m not providing a good way to test that that worked, just look at your config and trust me:
redis-cli -h 172.17.42.1 -p 6379 lrange frontend:wp.io.fliglio.com 0 -1
1) "wpdemo"
2) "http://172.17.42.1:49154"
3) "http://172.17.42.1:49156"
comments powered by Disqus