Friday, April 24, 2015

Example Docker Development Environment

Below is an example of how to create and distribute a full end-to-end development runtime environment to your team using Docker.  This allows for file edits and builds on a local machine (e.g. Macbook, also applicable to Windows with compatible scripts) which is exposed to a Docker image via a volume.

First define a local structure containing all the files needed by your Docker image runtime as well as some helper scripts.  e.g.

$HOME/<YOUR PROJECT>
   <SOURCE PATH 1> (e.g. Java app source, files built here using Maven to create WAR or exploded WAR - referenced by JBoss)
   <SOURCE PATH 2>  (e.g. UI app source, files built here using Grunt - referenced by Apache VHOST)
   <SOURCE PATH 3> 
   <SOURCE PATH 4>
   script_support (files supporting scripts below)
init.sh
checkoutAll.sh
buildAll.sh
getContentSkipVideo.sh
forwardBoot2dockerPorts.sh
updateHosts.sh
getDockerImage.sh
runDocker.sh

The structure should be created by a checkoutAll.sh script which gets all files from source control. e.g.


This ensures everyone is checking out files in the same location.  This is key as the Docker image is designed to know where files are based on these paths, Apache and JBoss configuration files, built Java and UI files, etc.

To build a new development machine from scratch to use this environment an init.sh script can be used (see bottom of post for complete new developer setup).  e.g.


Other local helper scripts...

buildAll.sh - Builds all files checked out from source control with checkoutAll.sh

getContentSkipVideo.sh - Rsyncs all content from a source server e.g. CMS or other server with large static files, images, etc. (example also includes an rsync filter to skip video)

script_support/exclude_video - Filter containing extensions to skip in rsync

forwardBoot2dockerPorts.sh - Forwards ports from your local machine to your boot2docker VM

updateHosts.sh - Updates your local /etc/hosts file to map your dev domain (e.g. devdomain.yourdomain.com) to your boot2docker IP (particularly important if you have named VHOSTs)

getDockerImage.sh - Pulls Docker image from repo (what your team uses to refresh their image when you rebuild)

runDocker.sh - Runs Docker image with port forwarding, host mapping, and attaching volume to local structure described earlier (VHOST looks for files in this volume on your local machine)

Now the Dockerfile that supports this environment...

This Dockerfile is in a directory named after the image with the following contents:

supervisord.conf - Starts all the processes (Apache, JBoss, etc) that we want to start when the image is run (also includes a nice splash screen to provide instructions to the user on start via the console)

bootstrap.sh - Shell script run with the image to kick off supervisord and shell

And that's it!

Build your docker image...

docker build -t <YOURNAME>/<IMAGE NAME> <DIRECTORY WITH DOCKERFILE AND SUPPORTING FILES>

Push your docker image to the repo...

docker push <YOURNAME>/<IMAGE NAME>

To get started with a new development machine:
  1. Install Node https://nodejs.org/download 
  2. Install Boot2Docker http://boot2docker.io (and anything else you might need to manually install)
  3. Download local directory with scripts (e.g. checkoutAll.sh) to your $HOME directory
  4. Run boot2docker Application, which starts a shell and run:
    • cd $HOME/<LOCAL DIRECTORY>
    • chmod u+x *.sh
    • chmod u+x script_support/sshpass
    • ./init.sh
Technically you can set up your local shell to run Docker commands, but it's just easier for your team to run these commands within boot2docker.  They can still do their builds and anything else in a regular shell.