Orchestrating a Docker development environment using Fig on OSX
I’ve been looking at a nice way of putting together a standard development environment for the platform I develop.
We’re a small group and develop on Macbook Pro’s. Our production system runs Linux. I’d noticed that some of us were using newer versions of, say JRuby or MySQL than others. Its not a massive issue but a part of my brain started twitching as its far from ideal.
Enter Docker. I’ve been intrigued by Docker since summer last year when it was kicking around version 0.6 but I’ve not really had much opportunity to use it ‘in anger’. I’ve settled for containerising a few odd bits and bobs on a VM which lives on my media server.
Migrating to docker for our production environment is in the longer term roadmap but this was an excellent opportunity to have a play now and gain some real world experience of it.
Enter Fig — this is actually a Docker project. I heard about this via a post on Reddit and digested the excellent web page on the train home.
A lot of tutorials I found on the web were a little outdated (which caused some head scratching when I came to update configuration files — more on that later). They also take the simpler approach of starting with a brand new project. I am going to Docker-fig-arise (I reserve the right to make up words) an existing application. Its not much of a jump, but if this helps someone then, hooray.
Enough talking
Services which make up the platfom I’m going to Docker-fig-arise.
- Ruby (JRuby in my case, this will change in the future)
- MySQL
- Memcached
I could stick all of these into one Dockerfile and run them together. Meh — thats no fun.
I could go some way to duplicating how the platform is set up in the real world. Three containers for each concern (service), web, db and memcached server. Lets do this. Oh, I’m ignoring Nginx and the load balancer because I’m not that bothered about those right now.
Application (web)
This is the Ruby on Rails section of the platform. I’m going to make use of the official JRuby Docker Hub containered version and then add a few more things:
Dockerfile
This file lives in the root of the platforms git repository.
MySQL and Memcached (db and memcached)
I'm going to call on Docker Hub again. Why re-invent the wheel?
Side note: I'm using memcached in a Fedora container because after a bit of trial and error, it was the one which worked best for me. I'm not bothered that it isn't running in the same type of container.
Sticky tape
Fig will magically create containers for these three services and stich them together.
fig.yml
This file lives in the root of the platforms git repository. A description of the file contents is detailed here.
Quick note about the environment variables for 'db'. I've just specified the root password here, which is sufficient for this development environment. However, MYSQL_DATABASE can be added to create a database to which the MYSQL_USER (with MYSQL_PASSWORD) will be granted all permissions.
Application configuration
I'm talking here about config/application.yml and config/database.yml. Specifically what are the hostnames (from the web point of view) for the db and memcached containers?
MAGIC! Fig has added details to the web /etc/hosts for 'db' and 'memcached'. Simply update your yml files as appropriate eg:
Seriously, don't use root!
Build it
We need to execute the Dockerfile and build our 'web' service. This will grab the base JRuby container from Docker Hub.
$ fig build
Once that's completed it should simply be a case of starting the services. During this command, the 'db' and 'memcached' containers will be grabbed from Docker Hub.
$ fig up
Adding a -d will put this into daemon mode.
Handy commands:
- fig logs — show logs for services.
- fig ps — what services are running.
Gotcha
As outlined above, I'd hoped to use this to unify our development environments, especially with the ability for Docker (well, boot2docker) to mount volumes on the host in they way you'd expect.
There is an issue (which is being discussed on the boot2docker github account), relating to the speed of the volumes when large amounts of files are written (and read).
At present this issue makes the use of the setup described above unworkable for developing. The current workaround (and most likely long-term solution) is to use NFS. Hopefully this will be added to boot2docker soon.