Docker helps you develop and ship code and data more efficiently. Taxonworks is a Ruby on Rails app that facilitates biodiversity informatics research. Instead of installing Taxonworks directly to our local machine, we’ll build some portable containers that anyone can run on any host operating system: OS X, Windows, or Linux. Docker containers will help make our work reproducible and portable, separating our development environment from any OS-specific dependencies.
Well, almost. To run docker on Mac OSX or Windows you’ll first need to install Boot2Docker. Boot2Docker provides a Docker-configured Linux virtual machine that will run in VirtualBox or whatever VM platform you have. The boot2docker VM will serve as the host machine for our Docker containers. If you already use Linux on your desktop then you’ll ignore Boot2Docker and just install Docker.
Let’s build some portable containers for the Taxonworks app and the Postgresql database.
With Boot2docker installed: boot2docker ssh
Get Boot2docker’s IP address on your host machine. We’ll need this later to access our app in a browser:
boot2docker ip
Get the Dockerfile.
The Dockerfile I’ve created for Taxonworks does a few simple things. First, it instructs Docker to base a new Docker image on Phusion’s Passenger Ruby image for the Ruby version (2.1) we need. Next it maps my Taxonworks app directory to the image. Finally, it instructs Docker, using the run
command, to execute bundle install
.
docker@boot2docker:~$ docker build -t jstirnaman/taxonworks .
Now, get a new Docker container for Postgresql + PostGIS. I chose James Brink’s image which also has good documentation:
docker@boot2docker:~$ docker run -P --name taxonworks_pg -e PASSWORD=`openssl rand -hex 10` -e USER=taxonworks -e SCHEMA=taxonworks -e POSTGIS=true jamesbrink/postgresql
More configuration options for the Postgresql container.
The --name
option specifies a friendly name for the container. Without it, Docker will assign a random name.
The docker ps
command should display the running container for our Postgresql image. In the Ports column is a list of ports open on the container and the host (boot2docker in our case) port that the container’s port is mapped to. In this case, host port 49158 is mapped to container port 5432, the Postgresql default.
docker@boot2docker:/Users/jstirnaman/dev/play/taxonworks$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
99d1655eb744 jamesbrink/postgresql:latest "/var/lib/postgresql 2 days ago Up 2 days 0.0.0.0:49158->5432/tcp taxonworks_pg
Next, we’ll startup a Taxonworks app container and use Docker’s container linking feature. Linking containers allows us to to link our Postgresql db securely to our Taxonworks app without keeping track of network addresses. Docker will handle that for us.
I’ve already configured taxonworks/config/database.yml to connect to a database host named db
. Now, when I run my Taxonworks app container I’ll specify the --link
option and assign the alias “db” to my Postgresql container. You can call it whatever you want – just make sure that your database.yml and alias match because Docker will create an entry in your app container’s /etc/hosts for the alias. This entry maps the alias to the Postgresql container’s IP address. Brilliant!
To illustrate with docker run
, bring up the container and execute the env
command so we can see the special environment variables created by Docker for our database connection. By default, the app container exposes standard HTTP ports 80 and 443 so we’ll use the docker run -p
flag to map port 80 in the container to port 49555 on our host machine.
docker@boot2docker:~$ docker run --rm --name taxonworks_web -p 49555:80 --link taxonworks_pg:db jstirnaman/taxonworks env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f01881df5463
DB_PORT=tcp://172.17.0.27:5432
DB_PORT_5432_TCP=tcp://172.17.0.27:5432
DB_PORT_5432_TCP_ADDR=172.17.0.27
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/taxonworks_web/db
DB_ENV_PASSWORD=7aaba37e0c3ca5cffa26
DB_ENV_USER=taxonworks
DB_ENV_SCHEMA=taxonworks
DB_ENV_POSTGIS=true
HOME=/root
Follow the Taxonworks installation instructions for running migrations and seeding the database. Because we assigned the container a friendly name in our docker run command and because our Dockerfile sets the Taxonworks install directory as our default directory, we can do this:
docker exec taxonworks_web rake db:migrate RAILS_ENV=test
docker exec taxonworks_web rspec
docker exec taxonworks_web rake db:seed
Finally, start up the Taxonworks Rails app using the default Webbrick server. As we saw earlier, the app container exposes standard HTTP ports 80 and 443 so we’ll instruct rails server
to listen on port 80.
docker exec taxonworks_web rails s -p 80
Taxonworks should be browseable at the boot2docker IP address and port 49555