Docker has quickly become the favorite virtualization tool for many people including myself. A few months ago we were discussing various technical goals across our project and things started to come together pointing to a basic docker framework to facilitate our development processes. This basically sums up our wish list:

Our Goals

  • Faster developer sandbox set up to get started on projects sooner.
  • Consistent software stack across developers, testing infrastructure, and production.
  • Ideally, a basic tool set that would work for both our new projects as well as our maintenance sites.
  • Start using the cool new trendy docker.

Container configuration with fig

One challenge is to have portable configuration for the building, starting, and stopping of a project’s containers. The fig project provides an elegant solution and the configuration is in YAML files, which we in the Drupal community should be getting used to now with Drupal 8. The fig.yml defines your containers, ports, mount point, and how they link together. Maintaining a fig.yml file in our project repositories allows us to do things like add an Apache Solr container with ease.

I was working on a collection of bash scripts and docker files and a fig.yml for one project and at some point it became stable enough to extract for general use. I brought these files together and made them available on github.

Introducing Bowline

Following the nautical and shipping metaphor, I chose the name bowline because it’s a simple and basic knot with multiple uses. The idea is that Bowline ties it all together. Plus it reminds me of my sailing days when I could tie a bowline in less than 3 seconds, which is slightly faster than it takes to start the docker containers.

Code and instructions found at the git repo: https://github.com/davenuman/bowline

I have now had success with Bowline on both new project and on existing Drupal 6 and 7 projects. Just last week I also tried it out with Drupal 8 and I’m happy to report that it works just fine on Bowline as well.

Dockerfile flexibility

Out of the box, Bowline ships with two containers. One for mysql 5.5 which is simply the default image from Docker Hub. The second is the web container providing apache, php 5.4, and related software. The web container is defined within the .docker/web-5.4 directory and the Dockerfile with supporting config files are based on the awesome work of the new Drupal testbot project.

Automation, running tests

Imagine your developers getting their local sandboxes up and running in a matter of minutes. This is now possible, facilitated by a few simple bash scripts. Bowline provides a template document intended for instructing your team on how to get set up: https://github.com/davenuman/bowline/blob/master/sandbox.md

Basically, they run build sync-db to get a copy of the database, build sync-files to get the site’s uploaded files, then build import which does all the work of building the docker containers and importing the database. There is also a backup script which will save a snapshot of your database named after your current git branch which is handy for switching to another task while preserving your work.
The run command is intended for running your automated tests. It assumes behat but you can modify it to run whatever testing software you use. The nice thing is that our developers are all running local behat tests on the exact same software stack as each other and as the test server. We have a Jenkins server with docker and have jobs configured to execute the build and run commands just like we do on our own machines.

Slaying File Permission Dragons

Anyone who has worked with a LAMP stack has bumped into file permission issues with uploaded files. Add a docker container to the mix which is mounting your project files and serving them up as the apache user withing the container and there is lots of ways to mess things up. This dragon gave us some grief early on when starting to use docker in this way. We won the day by setting the apache user to run with the same uid as the docker host user. This way each developer will have ownership to their own file uploads on their system. Here’s the simple bash code that makes it possible:

# Set the apache user and group to match the host user.
OWNER=$(stat -c '%u' /var/www)
GROUP=$(stat -c '%g' /var/www)
usermod -o -u $OWNER www-data
groupmod -o -g $GROUP www-data

(source)

Room for improvement

One tricky thing we found using docker containers is using drush in a complete way, particularly using drush site aliases. For now we have “crush” which is a temporary work around but not too bad of a work around actually. Crush is a simple bash function that calls drush as a command on the docker web container. We use crush to clear cache manage features and such, and it is working well. However it’s not ideal and I’d like to add ssh server to the stack to allow for proper drush site alias usage.

There’s always room for improvement. I’d like to find an elegant way to incorporate more developer tools such as sass, compass and debugging tools. Every project is different but it would be nice for Bowline to have some basic Behat smoke tests build in. These things will hopefully be added to the Bowline project as we use it and add things to our drupal project. And yes, pull requests are welcome.