Creating immutable servers with chef and docker.io
September 7, 2013
Building applications in a docker.io Dockerfile is relatively simple, but sometimes you want to just install the application exactly as you would normally via already built chef cookbooks. Turns out this is actually pretty simple.
The first thing you’ll need to do is build a container with chef-client and berkshelf installed. You can grab the one I’ve built by running docker pull paulczar/chef-solo
or build one youself from a Dockerfile
that looks a little something like the following…
Creating a docker.io container with chef and berkshelf
# DOCKER-VERSION 0.5.3
FROM ubuntu:12.10
MAINTAINER Paul Czarkowski "paul@paulcz.net"
RUN apt-get -y update
RUN apt-get -y install curl build-essential libxml2-dev libxslt-dev git
RUN curl -L https://www.opscode.com/chef/install.sh | bash
RUN echo "gem: --no-ri --no-rdoc" > ~/.gemrc
RUN /opt/chef/embedded/bin/gem install berkshelf
you’ll notice I’m using the embedded chef ruby to install the berkshelf gem, this is a handy shortcut to avoid messing around with random ruby versions from your distributions packaging.
run $ docker build -t paulczar/chef-solo .
to build a usable docker container from the above Dockerfile
.
Using chef-solo and berkshelf to build an application in a docker.io container
My example application will install Kibana3
to your docker container. I’ll step through how it works below.
Chef-Solo
To run chef-solo
successfully we require two files. solo.rb
to set up file locations, and `solo.json’ to set up the json / run list required for your application.
root = File.absolute_path(File.dirname(__FILE__))
file_cache_path root
cookbook_path root + '/cookbooks'
{
"kibana": {
"webserver_listen": "0.0.0.0"
},
"run_list": [
"recipe[kibana::default]"
]
}
Berkshelf
To run berkshelf
we need to build a Berksfile which contains a list of all the chef cookbooks required for the applocation. Berkshelf will download these cookbooks to a local directory which will be usable by chef-solo.
site :opscode
cookbook 'build-essential'
cookbook 'apache2'
cookbook 'git'
cookbook 'kibana', github: 'lusis/chef-kibana'
cookbook 'nginx' , github: 'opscode-cookbooks/nginx'
You can see some of the cookbooks are being pulled from the opscode repository, whereas others are being pulled directly from github.
Dockerfile
All that’s left now is to create a Dockerfile that will bring it all together.
# DOCKER-VERSION 0.5.3
FROM paulczar/chef-client
MAINTAINER Paul Czarkowski "paul@paulcz.net"
RUN apt-get -y update
ADD . /chef
RUN cd /chef && /opt/chef/embedded/bin/berks install --path /chef/cookbooks
RUN chef-solo -c /chef/solo.rb -j /chef/solo.json
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
CMD ["nginx"]
Run $ docker build -t demo/kibana3 .
to build your application.
It will add the local files ( solo.rb
, solo.json
, Berksfile
) to /chef in the server and then call berkshelf to download the cookbooks and chef-solo to install your application. Finally it will give nginx
a directive to run in the foreground so that we don’t have to do any sneaky prcess control to get it to work with the way docker.io
runs processes.
To run the resultant docker.io
container you simply need to run $ docker run -d -p 80 demo/kibana3