A New Chapter

A couple of years ago I was a relatively new face in web development (and if I’m being real, I still very much am). I had a lot to prove and a lot of motivation to prove it with. I was bright eyed and bushy tailed. There was a skip in my step (or a hop in my stride - whatever the kids or saying these days). I had a lot of passion and an endless supply of motivation. Unfortunately, I’ve noticed a very sharp contrast between the me of then and the me of now.

It’s been a good run and there is a lot I’m going to take from my experiences but It’s time to move on. It’s time to say goodbye to Ruby on Rails.

Installing gems used to be an exciting process for me.

I spend a lot of time thinking this over and it was by no means an easy decision. I fully recognize I’m throwing a lot to the curb here and getting into something new from scratch will make an already uphill battle even more difficult. I’m going to have to build new relationships and learn new things. As someone who has trouble in both of those fields, that’s a very intimidating prospect.

Even considering all that, I know I made the right decision because I’m not doing it to make things easier. I’m doing it because somewhere in my heart I know it needs to happen. I’m doing it for me.

Before anyone gets upset, Ruby development hasn’t changed in some crazy way that has made me frustrated. It hasn’t gone in some direction I don’t agree with or anything like that. If anything, I’m the one who has changed. Rails development just isn’t fun anymore and if I can’t have fun then what’s the point?

Those close to me deserve better than someone who is constantly frustrated but too afraid to make a move on his career. Today I’m finally making that move.

It's been fun WEBrick. Gonna miss ya buddy.

I haven’t 100% decided where to go from here. Maybe I’ll get into Laravel. Or perhaps I’ll take my career into a whole other direction (I’ve always wanted to get into game development). I’m totally up in the air about it.

What I do know is that I have one last Rails app to finish this year and after I’m done with that I’ll be in uncharted territory again. For the first time in a long while I feel like I have the freedom to have fun and love my job again without outside influence making me feel like I’m trapped.

I hope I will have your support as I close another chapter in my life and get ready to write the pages of a new one.

Ruby on Rails Development With Crane for Docker

I’ve been searching for a solution for a Ruby on Rails development environment since Docker and LXC first hit the spotlight in the Linux community. Using Linux containers is far more appealing than a Vagrant setup mostly due to the lower resources containers use over traditional emulation.

My search originally brought me to Fig and then later to it’s fork Docker Compose. Both of which had major issues getting Rails up and running.

Finally, a friend suggested Crane.

Setting Up Crane

First download Crane and add it somewhere in your $PATH. The following command will install Crane on your machine for all users (Linux and OSX):

1
$ bash -c "`curl -sL https://raw.githubusercontent.com/michaelsauter/crane/master/download.sh`" && sudo mv crane /usr/local/bin/crane

An install for just the current user might look like this:

1
2
3
4
$ mkdir ~/bin
$ bash -c "`curl -sL https://raw.githubusercontent.com/michaelsauter/crane/master/download.sh`"
$ mv crane ~/bin
$ export PATH=$PATH:~/bin

As of the writing of this article, Docker (>= 1.3) is a hard requirement. If you need help installing Docker for your operating system I recommend reading the Docker installation documentation (OSX users will require the extra step of installing boot2docker as OSX does not have the native LXC support Docker.)

Once you have Crane and Docker set up, we can start creating our containers.

Creating The Ruby Container

First thing we need is a ruby application to run:

1
$ rails new example -B -d mysql

Next we need a container for our ruby application. This one will work nicely for now:

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM ruby

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /app

WORKDIR /app

RUN gem install rake

ADD Gemfile* /app/

RUN bundle install
RUN rm -f Gemfile*

Copy and paste this into a file called Dockerfile in the root of your project.

The container’s state after the Dockerfile is processed will be it’s state when it runs our application. As such, we need to make sure all of our gems are installed and ready.

Setting Up Crane

The next step is to tell Crane how to start our containers. Create another file in the project root and name it crane.yml. Add the following to it:

1
containers:
  app:
    image: app
    dockerfile: .
    run:
      volume: [".:/app"]
      cmd: ['bundle', 'exec', 'rails', 's', '-b', '0.0.0.0']
      link: ["mysql:db"]
      publish: ["3000:3000"]
      env:
        EXAMPLE_DATABASE_USERNAME: root
        EXAMPLE_DATABASE_HOST: db
      detach: true
      tty: true

  mysql:
    image: library/mysql:5.6.22
    run:
      publish: ["3306:3306"]
      env:
        MYSQL_ROOT_PASSWORD: root
      detach: true
      tty: true

You might notice I’m using a few environment variables here. The MYSQL container requires us to set MYSQL_ROOT_PASSWORD so a root user can connect. The other two variables, EXAMPLE_DATABASE_USERNAME and EXAMPLE_DATABASE_HOST, tell our Rails application how to connect to that database. The reason we use db as the host is because of the link directive in our application definition. It tells Crane to make the container mysql appear as db:// on the app container’s local network.
`

Setting Up Rails

The final thing we need to do is set up Rails for our new environment.

Edit your config/database.yml to match the following:

1
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: <%= ENV['EXAMPLE_DATABASE_USERNAME'] %>
  password: <%= ENV['DB_ENV_MYSQL_ROOT_PASSWORD'] %>
  host: <%= ENV['EXAMPLE_DATABASE_HOST'] %>

development:
  <<: *default
  database: example_development

# Truncated for space.

Here we make use of those environment variables. Notice how DB_ENV_MYSQL_ROOT_PASSWORD is [container]_ENV_[variable]. We could have set up another variable for this, but no sense in setting the same variable twice if Crane already does it for us.

Starting The Container

We can now start the container.

1
2
$ crane provision
$ crane lift

After some text flies across the create will be ready to view the application at localhost:3000. You will notice a familiar error, however.

database-error.png

Right, we haven’t run rake db:create yet.

In order to do that we are going to need the unique ID of the container running our application:

1
$ crane status app

Copy the bit of text under ID.

Now we can send commands to our container.

1
$ docker exec -t [your cid] bundle exec rake db:create

And if migrations are needed:

1
$ docker exec -t [your cid] bundle exec rake db:migrate

Assuming that’s all you need to do your application will now work:

no-error.png

And that’s that, a Rails development environment on Crane.

The source code for this project can be found on Github.