The current state of Rails deployment - ruby-on-rails

A few years ago it seemed fairly tricky to get a rails application deployed. However, from what I have been reading recently it seems that rails has improved much in this area. However, given the various versions of Ruby and gem dependency issues, is deployment still a headache (to heroku or engine yard, for example)?

No. Heroku makes deployment ridiculously easy: it's entirely managed by Git, your app is isolated so there are no dependency conflicts, and it's free for small scale apps. Other services like EngineYard and DotCloud offer similar service (although EY isn't cheap and DotCloud isn't as ruby-focused).

There are a bunch of tools to make deployment and management easier for you.
Heroku
Heroku is totally managed by git via the heroku gem. Essentially, you call heroku push instead of git push and your changes get pushed to the server, built, and your site is automatically updated
Bundler
Bundler has made managing gems a lot easier, and it is super straightforward.
RVM
RVM is actually a good tool to use on servers. It allows you to have one server serve multiple Rails applications, each on a different version of Ruby, with it's own totally unique Gemset (This means that you won't have gem conflicts for multiple apps using the same ruby version. Gem conflicts are gone!).
Capistrano
Capistrano lets you define everything you need to happen during deployment, and allows you to start and end it all with one simple command - cap deploy. It greatly simplifies the deployment process.
Foreman
If your application requires multiple services to start (Server, Delayed::Job, Sphinx, etc), Foreman is the tool for you. It lets you define what services you need, and start them all at once by calling foreman start. It works nicely with Capistrano, and makes the console output of your services nice and easy to read.
Overall, I'd say that the state of Rails deployment is an order of magnitude better than it was a few years ago, but there's always room for improvement. The projects mentioned above are a good start, and it's just a matter of finding what fits your organization best.

Deployment might be a headache depending on your needs. If you're running a single application in a server, it's easy to build it, install ruby and setup your deployment environment using Capistrano (here's a sample of how to do it using Nginx and Unicorn).
If, on the other end, you require many different applications on your server (possibly running on different rubies and groups of gems), you'll have more work but it's completely possible. To have many different rubies installed at the same time without conflicting with each other you'll use RVM and to make sure all your app dependencies are defined, your Rails app has to use Bundler (or maybe something else that does the same).
So, your requirements are going to make it simpler or not, but is isn't really impossible and it won't drive anyone crazy with the amount and quality of tools available for the job.

Related

Deploying Ruby on Rails Apps with Mongoid (MongoDB), Redis, Resque, Capistrano, etc

I am creating a Ruby on Rails website deployed on AWS. I am running into configuration issues and I can't seem to find docs/tutorials that cover configuration of the various tools mentioned and how to set them up BOTH for ease of use in development (on localhost) and while deploying.
Right now I have a Rails app set up and I am using Bundler for all my Ruby gems.
I have two major goals.
Ease of development - Ideally somebody should just have to clone the repo and run 'rails server' and should be good to go. All other stuff like Redis servers, Resque workers, Mongo DB databases, should automatically be started/created.
Ease of deployment - Given some configuration file (like YAML files), I should be easily able to deploy to various stages by simply running 'cap production deploy' or something similar. It should automatically run all the rspec tests, and prevent deploying if something goes wrong. Once deployed it should also handle all other aspects like restarting Apache/Nginx, handling DB migrations, restarting Resque workers, etc. I know how to do this all manually, but again I am looking for a solution that will let a novice (i.e. unexperienced with my app's deployment process, not novice in general) easily be able to deploy.
I have looked at various tools/gems like Foreman, God, etc. but I am not clear on how to use them correctly and how they work in different environments like development and production.
I am looking for either docs/tutorials on how to do this or even Github repo's of Rails app that have solved these problems (preferably smaller repo's so that I don't have to wade through application specific stuff to get the information I looking for).
I am also looking for a way to monitor my Rails app. As what kind of errors are happening? how frequently are they happening? Is Splunk a good tool to do so?
Note : I am not tied down to use any of the tools mentioned above, since I am only starting to develop my website.
This is pretty comprehensive if you want to deploy to a small EC2 instance using Capistrano and Apache.
For monitoring I'd suggest New Relic or just checking your logfiles.
However, you're going to have to be more specific about your technology questions. You're covering a lot of breadth here and going deeper into answering this would require a lengthy essay and possibly a consulting fee.

Ruby on Rails app : from Heroku to a local server : what are the main steps?

My Ruby on Rails app (basically a commenting and voting system) has been deployed and currently runs on Heroku. I need to deploy it on a local server to ensure an optimal performance for a customer-organized event in a location where the internet bandwidth is too low and unpredictable to support the 100+ simultaneous users.
Just as Ruby, Rails, Javascript, JQuery, AJAX and CSSs were new to me a few months ago, going local is something new I need and am eager to learn (which should also allow me to deploy onto a dedicated or virtual private server if needed).
The following elements are obviously on the way : choosing an operating system, installing Ruby on Rails, a web server, a database engine and deploying my app code and data of course but I need help to make sure I do not forget anything and really understand how all of these elements must be tied together to get my app running.
At a reasonably high level, starting with my app code, could you please share your experience and tell me the steps I need to take from scratch to have it run on a local server ?
If you have a Mac, then you're already most of the way there. I do all of my Rails development on OS X. The steps from there are pretty easy.
Install Homebrew. This will help you quickly install any dependencies on the Mac that your Rails app needs (such as a database). Since you're on Heroku, you're likely using Postgres. So with Homebrew, you can install Postgres via brew install postgresql.
Copy your app code somewhere that makes sense. I have all my apps inside my ~/Projects directory.
Recommended: Install RVM. This will help keep gemsets unique to projects and keep your global gemset clean.
If you're using bundler, do bundle install within your app's directory.
Within the app directory, do: rake db:setup (Note: This may require prepending bundle exec)
Start your server. I tend to use Unicorn (see Heroku's deployment with Unicorn for even more details), so this would just be unicorn. Else, rails s works as well.
Those are the high level steps to get a local server running.

Rails Production Environment

I'm new to rails have been searching for deployment guides on the web - it's quite fragmented. I see some which recommend deploying as a sudo enabled user. I was thinking you would create a user with no sudo powers to run the app for security reasons. It would need it's own home directory for RVM and bundler but having sudo powers seems redundant and a security risk. I'm doing this all manually as it's a tricky beta level application and deploying it is not yet straightforward, so capistrano would only be a layer of obfuscation at this point.
I'm using thin as the server with Nginx as the proxy and redis and Postgres as the database. Clockwork and sidekiq as well.
Capistrano seems like a lot of work even for a small project but it's worth getting setup anyway if you have hopes of the application growing (and thus the complexity of deployment increasing).
I personally like the idea of separating the distribution specific Ruby available (and gems) to an RVM deployment specific to the application. Furthermore, requiring bundler to manage gem dependencies and ensuring compliance is invaluable. I wouldn't suggest enabling sudo for that user; it'll expose the whole stack from HTTP requests to root level OS control. Applications shouldn't require administrative access, deployment scripts might.
If you're new to Rails I'd recommend something simple for your first deployment. Heroku allows you to deploy apps by simply doing a git push to their repository. They handle all the steps necessary to make your app available on the Internet. Best of all it's free as long as you don't need heavy resources.
EngineYard is another hosting solution that's easy to deploy to and step up from Heroku in terms of flexibility (and cost).
Once you're comfortable with deploying production apps then you can look to using your own servers and using capistrano for the ultimate in customization.
I have production websites running in both environments and I've yet to need to go to the trouble of migrating to my own hosted server.

Use Capistrano for Rake tasks?

Is Capistrano only used for deploying Rails apps?
Basically I want a scripting framework to handle all server/client scripting for me.
Examples:
Updating Ubuntu, installing gems with dependencies etc.
Creating a new Rails app, Git initialize it and commit, create Heroku project and upload the app.
Automatize basic file/folder operations
Should I consider to use Capistrano for this (cause it can handle server/clients) or should I just use Rake for it?
Capistrano could do everything Rake could, but not the other way around?
What are the pros and cons with each?
A few attempts have been made at making capistrano more universal - capistrano-boss and my own capistrano-provisioning, for example - it may be that somebody has already done it. Certainly, in terms of running commands remotely and organising tasks, namespaces, hooks etc, capistrano is second-to-none. But I've yet to see a comprehensive solution that allows you to really administer remote systems using it.
Have you investigated chef? It seems that this is frequently used in conjunction with cap. 37signals, for example, have extensive chef recipes available - and they were also the source of capistrano.

Why is it supposedly "hard" to deploy Ruby on Rails to production?

I admit that I don't follow much of anything "right" on deploying test versus production code. I have been using ASP.NET, and I typically run it locally in Visual Studio, it works, I upload it, I test it again on the production server.
I have read several people say that deploying Rails apps is harder and there are special programs/ways on the ruby site about deploying RoR. I've only toyed with RoR. What is special about deployment? You don't just copy and paste the code and run it (from development machine to the production)? Is it because one is in Apache and the other running on the built in server?
This will be on a Mac Server if it matters.
Deploying RoR is not difficult anymore, especially with Phusion Passenger.
What is somewhat difficult, is getting a automated production environment setup with capistrano, vlad, etc. If you don't mind simply copying your code to the server, you can do that just fine. Most people choose not to do it that way because you lose out on a lot of the benefits that the automated deployment tools give you.
I guess people consider a Rails app harder to deploy than say some PHP apps or such where you just plop the code somewhere and point Apache or whatever at it. But, as mentioned above, you could do that now with Phusion Passenger.
We use Nginx+Passenger, but not for simplicity of deployment. Capistrano is our deploy tool of choice, and really, unless you have a very simple app, you're going to want something like Capistrano anyway. For example, with our deploy, we do a slew of things:
run any database migrations
generate release notes automatically, based on all the commits to Git between the last deploy and this one
notify various people via email (with differing lists depending on whether the deploy is to our staging environment or production) - we do this via cap_gun which integrates with Capistrano.
Notify New Relic RPM of the deploy so it can mark it in our RPM analysis
Notify Hoptoad of the deploy, so it too can have that data when reporting any exceptions
produce our sitemap.xml file, and ping Google to tell them there's a new one
update crontab files (I store our crontab files for each server in our git repo, and then on deploy it sees if there is a new version and updates accordingly, etc.).
flush/restart memcached
There are other ways aside from Capistrano, but it's a proven tool, with a lot of flexibility, yet pretty simple to setup a vanilla configuration.
So, my take is that once you get into any app that is beyond just the very simplest of apps, you're going to need/want to be doing things other than just simply updating the code. In the beginning though, if you just need the code updates, and maybe Rails migrations, then you can do simpler things like Passenger and code sync, or look at tools like Heroku or Engine Yard's stuff where they do a deploy by doing a Git clone (and then offer some additional abilities).
Another super easy way to deploy is with http://heroku.com/
Some of the issues you face with deploying rails to production:
Database connection.
You need to be sure that the database connector is set up for the production environment.
Database migrations.
You have to run database migrations against the production database even though you may have already run them in production/testing/staging
Ruby version. The version or sub-version or Ruby can trip you up, e.g. An error occurred while installing debugger-linecache (1.1.1), and Bundler cannot continue
Gem dependency.
Your production environment may have different packages and gems from development. Bundler will figure this out for the most part and install the dependencies but occasionally there are still issues that you have to resolve manually.
Dependencies.
Some gems on some machine have particular dependencies. I have seen frequent problems with using gems on my unix box that work on OSX and vice-versa.
Note the last 3 shouldn't affect you if on the same machine but I included them based on the title and to be comprehensive.
It's not especially hard. If you stick to conventions then with a little bit of configuration it boils down to this:
cap deploy
...however there is sometimes a bit of effort needed up front to get the workflow in place.
The good news is that lots of people have packaged up solutions and stacks for RoR that you can just plug and play. For example, google ec2onrails - this is a packaged Ubuntu image and set of capistrano tasks for running rails apps in Amazon's EC2 cloud, with lots of common stuff set up already out of the box.
Choose a good hosting provider and you should be able to find something similar for that also.
An easy way to deploy Rails apps is to use Phusion Passenger. Deployment doesn't get much easier than that for any programming language or framework. You can do that on a Mac server.
Another really easy way to deploy rails is with jruby and the glassfish gem.

Resources