Development Environment with Rails

Standard

Currently, I favor development with Docker because of the ease of deployment. I see the benefits when in a team environment using Docker, onboarding is much easier. Similar to using virtual machines you have images with your development environment all set up but with docker (containers) the footprints are somewhat smaller. I say that because the standard ruby base image isn’t exactly a lightweight it’s still around 700MB+ in size. But you could use Alpine Linux base images for the surrounding services ie database, Redis, elastic search.

I have experienced a few development environments so I’ll go through and list my point of view. Note: nothing here is the absolute best or de facto, just what I’ve used in real-world development teams. 

Local System:

RVM, MySQL, Redis, etc. all installed using brew on the local system.

I think this is standard for most, quickest to start. Minimal initial setup cost.

Pros: Everything is snappy, you have access to everything and are in control of most things. If you are confident in *nix skills you could overcome a lot of issues and have more control of your system. Nothing extra to worry about, turn on the machine (wake the machine up) and go.

Cons: Setup – 0 to Development can take days if there are issues. Not all Rails developers are familiar with *nix commands. Not all developers setup there systems the same. Not all systems are the same, Linux, Mac, and Windows so one issue might not translate to another developer. Does not mimic production/staging, so you get a lot of the “Works for me!” shrugs. Lots of divergent setups and datasets (strange database issues) occur. Sometimes from a developer installing a different version of MySQL, reading the setup manual and following directions is sometimes hard.

Overall: Personally I still use a local setup to develop but once I get a little deeper into a project I transition to a Docker-based environment.

Remote Development Machines:

Physical or cloud-based server setups to mimic staging/production but for development. Imagine having a computer for every service you need: App server, Database server, Redis server, etc.

This was a unique setup but was actually one I got to experience. Each developer was setup with a blade server and we ssh’d and scp’d or remote shared working directories. Some devs used vim so they ssh’d in, some used remote shares so they could use Sublime, TextMate, or Atom. I was one of the Sublime users. 

I didn’t really know how data was replicated but I know now each developer had access to their own set of development, test, staging, production (sanitized) datasets. The production dataset was close to real-time replicated and sanitized.

Pros: All setup was done outside of developers control, you just needed to know how to connect to your development server. The database was a sanitized version of production data. Data bugs were so easy to find and work with.  Real 1 to 1 with production every service was replicated for each developer except load balancing and CDN. Systems can be any OS.

Cons: Cost! Network outages meant no one could work. Had to make group decisions on gems or technologies used, because everyone needed it installed on their servers. Or instances of machines needed to be turned up for all devs, ie. let’s use MongoDB, ok we need to provision 20+ instances of it.

Overall: Great experience but was overkill, extremely expensive. Network outages seemed like snow days, all devs would head over to sysAdmins area to chat. Data bugs were the easiest to figure out and fix using this method, we would see exactly what the client saw or experienced. I think this was the most impractical environment I have ever developed on. I had a MacPro that was pretty much a dumb terminal to a high-end blade server running 24/7 that was connected to other services that were either physical servers or cloud-based servers. This kept sysAdmins busy, but I think they would rather spend their time with other things than to babysit a bunch of unruly Rails developers.

Virtual Machines:

Vagrant, VMWare Fusion

Using VM’s is a great way to mimic production if your production uses several different systems, Windows, OpenBSD, or BSD. Vagrant makes it manageable and almost set it and forget it. This is a good balance of local development with prod system parity. 

Pros: System reflected production more. Didn’t have to spin up all services if you didn’t need or work on things that didn’t need it, I would not spin up Redis or ElasticSearch if I didn’t work on a feature that wasn’t using it. Systems can be any system that can be VM’ed, ie: Windows and BSD.

Cons: Slow at times. When working with an SOA, if you have lots of micro-services. It means you would have lots of virtual machines up and running. Resource intensive CPU, RAM, and sometimes HD space. 

Overall: This was my preferred method for the longest time. This was as close to production you could get without setting up multiple servers just for development.

Note: I have not used this method ever since I learned to use Docker for personal projects.

Docker Containers:

By far for me the easiest/fastest (YMMV)*, because I do love some sysadmin stuff. I actually like working with Dockerfiles and docker-compose. If you are using Docker in production it makes sense to use Docker in development as well. You can containerize your app and push that image up to prod.

* This is sometimes true when there are no bugs like stopping a container and still having ghost processes around. You have to really know what you are looking at and how to deal with it on your system. 

Pros: Containers are somewhat small in size compared to VMs. Can directly translate to production setup. “Forces” you to think about your system as small services or processes that build up into a larger system. Not big VMs that run and store everything. No real set up issues to get a system running, Install Docker ‘docker-compose up’ and system is good to go.

Cons: If developing purely in a container, you’ll either need to create command line aliases or tab complete a lot because of stuff like this:

I think a deal killer for me would be the random issues of processes not ending or strange stuff with Rails PID (the /tmp/pids/server.pid) gets stuck. You just have to sudo rm /tmp/pids/server.pid.

Overall: This would be great if your production is set up for Docker you can’t go wrong with developing in it as well. Takes the headaches (if you don’t like doing it) of setting up your development box. Even with some of the issues, I can honestly say the goods outweigh the bad.

So as you can tell I didn’t mind these environments. They didn’t hinder my development velocity or make me want to bash my screen in. They each have there merits and weaknesses some greater than others. Some took longer to get going but once you get into the grove of the environment, smooth sailing.

Personally, I use a hybrid environment. I set up like I am fully going to use Docker but I actually expose any services port the app would need instead of keeping it internal to Dockers local network. I also use volumes pointed at my gemsets, code, and anything else needed.

So I use RVM and I run all my rails commands (generate, test, bundle install, etc) locally connected to Docker containers with Redis, Postgres, Memcache, etc. But, I also run a close to production app container which I technically could run the same commands to get the same results. (I don’t like chown’ing the files I’ve just generated just so I can edit them on my local machine) 

That for some reason makes me sad.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.