This tutorial is an extraction from a talk I recently presented about docker and rails apps at the Barcelona on Rails user group. I’ll explain how to integrate docker into an existing rails app workflow.
Dockerizing our dependencies
The first step to integrate docker into our workflow is to start with our application dependencies.
As an example I’ll use the open source app fulcrum. I assume this application is running locally as would be the case with an existing rails app. For this example we’ll use the postgresql database.
So the first thing is to initialize our database container. For that we execute the following command.
So we’re creating a container and run it as a daemon (-d), we setup some environment variables (-e) for the username and password and make the ports available (-p HOSTPORT:CONTAINERPORT).
Now we need to adjust our config/database.yml, it should look something like this:
And now we run our rails app
Please note that for the value for the POSTGRES_HOST I’m using boot2docker, if you’re running on linux or against another docker host replace this accordingly.
Now when we visit localhost:3000 our app will be running against our database in a docker container.
For a more complicated app, we’d do the same for the rest of our dependencies. By starting with the dependencies, we are preparing the road so we can have a more decoupled environment while maintaining our regular workflow.
Dockerizing the app
The next step is to run the application itself inside a container. For this we’ll need to create our Dockerfile.
There are many different places to start from. We’ll use the official ruby 2.1.2 container since this is the ruby version our app needs, but defining our own from scratch is quite easy as well.
Our Dockerfile should look like this
We also need to tell docker certain files we don’t want as part of our container, we create a .dockerignore file like this:
After creating the files in the root of our app we execute:
Once that is finised we can run our app like this:
So what is this doing exactly? We’re linking our database container to our web container (–link), we’re exposing the port 3000 (-p) and we’re also setting environment variables (-e) with the values we used when creating our db container. After executing this we can go visit our app running on http://DOCKER_HOST:3000
The first thing we can see is that we have to set many duplicate environment variables from the database when running our container, fortunately docker allows us to have access to a linked container environment variables.
We can change now our config/database.yml replacing the username and password like this:
We rebuild our container again, and now we can start it simply like:
Now, recreating our container every time we make a file change is going the get very annoying quite soon. For this we can also leverage another docker facility called volumes. This will allow our container to have access to our local files. To do this simply we start our container like this:
Note: Please make sure you delete your .bundle/config local file to avoid issues with bundler inside the container.
Automating our setup with docker compose
At this point we have our app running successfully inside a docker container, but having to be typing this commands constantly is not fun.
To finish our setup we’ll use docker compose.
So let’s create our docker-compose.yml.
Now to run our app we simply do:
The first time we access our app it will complain our db is not created we can simply fix this by running:
And last but not least if you want to run your tests then you can simply do:
So that’s it, I hope this tutorial helps you get started with docker with your existing rails applications. If you want more info about docker compose, check out my article about fig (docker compose’s predecesor) here