Building Docker images using Chef

Chef is a great configuration management tool. It allows managing environments, supports multiple platforms, handles updates, but takes a lot of time to deploy software from scratch. Chef is not like Docker, which allows spinning up containers in seconds. If you are already using Chef, then you might not have time to rewrite all the Cookbooks into Dockerfiles. In this post, I’m showing how to build Docker images quickly using existing Chef Cookbooks.

Solution

The obvious way to build a Docker image using Chef is to create a container with SSH running and use knife to run chef-solo inside. I was looking for existing solution that already does that. I found that there is a Docker driver for Kitchen. The default driver for Kitchen is Vagrant which sets up a VM and deploys a cookbook. Using Docker driver a container is used instead, which you can convert to an image and push to the registry afterwards.

Example

I use nginx cookbook as an example (I know that there already is a better docker image for nginx). Following snippet clones the nginx cookbook, installs dependencies and deploys the cookbook into a docker container using Kitchen.

Make sure that you have installed latest Chef Development Kit and Docker Toolbox.
On OS X you need to run the ‘Docker Quickstart Terminal’ first.

git clone git@github.com:mbilski/nginx.git && bundle
kitchen converge example-ubuntu-1404

After that you should have a Docker container up and running with nginx cookbook deployed! Now you can commit the container and build an image.

$ docker ps
CONTAINER ID IMAGE COMMAND
fc1736a9f4bb lle95b668623 "/sbin/init"
$ docker commit fc1736a9f4bb chef/nginx
f99e7e70398edeb6c07a9277928f17cb1640cf6f52b08a7f23d3fd0a33dd1626
$ docker images
REPOSITORY TAG IMAGE ID
chef/nginx latest f99e7e70398e

Use following commands to run the image and test it.

$ docker run -p 8080:80 -d chef/nginx nginx -g 'daemon off;'
xc49e36da495d208618877cc0426b8578e4c7e072becec1c3dcd469615acb81f
$ echo $DOCKER_HOST
tcp://192.168.99.100:2376
$ curl 192.168.99.100:8080
<title>Welcome to nginx!</title>

How to configure Kitchen to use Docker?

If you have already .kitchen.yml then you just need to change the driver to docker. For more configuration options see kitchen-docker. This is the example configuration used by nginx cookbook.

driver:
name: docker
use_sudo: false
provisioner:
name: chef_zero
platforms:
- name: ubuntu-14.04
driver:
platform: ubuntu
image: ubuntu-upstart:14.04
disable_upstart: false
run_command: /sbin/init
suites:
- name: example
run_list:
- recipe[nginx::example]

Summary

I think this is a seamless way to migrate from Chef to Docker (at least for developers). You can use most of the Docker advantages without getting rid of existing Chef cookbooks.

https://github.com/mbilski/chef-nginx
https://github.com/portertech/kitchen-docker

comments powered by Disqus