I've setup a new environment with Ruby 1.9.2 and Passenger 3. A Rails 3 app is deployed with Capistrano. RAILS_ENV is set to staging.
When trying to boot the application, Passenger complains about a missing gem. Running
bundle --deployment
installs gems to RAILS_ROOT/vendor, but doesn't solve the error.
If I install the missing gem as a system gem (eg. sudo gem install), the error disappears but now the next gem in the Gemfile is reported as missing.
I could solve this by installing my gems to the system, but I'd like to understand why installing them to the vendor directory isn't working. My understanding is that the idea of bundler is to avoid having to keep all gems installed to the system.
I have RAILS_ROOT/.bundle/config set to:
BUNDLE_FROZEN: "1"
BUNDLE_PATH: vendor/bundle
BUNDLE_DISABLE_SHARED_GEMS: "1"
Ideally, gems should remain in a consistent location to avoid them being reinstalled every deploy. Therefore, try removing BUNDLE_PATH from your config (default location is ~/.bundle).
I'm not sure what bundle --deployment does (I couldn't see mention of this in the docs). I use something like this command in my deploy scripts:
after :'deploy:update_code' do
run "cd #{release_path} && bundle install --without test cucumber development"
end
Related
I copied the app from Github. Installed a proper version of Ruby using rbenv. I installed bundler by gem install bundler and ran bundle install --path vendor/bundle. All gems were installed in vendor/bundle directory in the app. Now I wonder, why rails s command doesn't work but bundle exec rails s works? The same with rspec command. Is this because I installed gems in vendor/bundle directory? I'm confused.
Also, when I run gem list I get only a few gems, but there are a lot of them in vendor/bundle directory.
Please tell me why gem list command doesn't see gems from vendor/bundle directory and why I need to run commands with bundle exec. Thank you!
The purpose of having the bundle exec command is to look/search for the command which you want to run inside the current bundle or installed gems inside your vendor directory.
If you are running newer rails (v5) then have a look at the binstubs which copies over the command executeable in the bin directory. So that you can simply call
bin/rails server
This is the same approach which is followed by the deployment solutions which we currently have. They create a .bundle directory which eliminates the need to do bundle install everytime.
Prefixing bundle exec to commands executes the command as it isn't of rails. To fix it we can simply run:
gem install rails
This will install all dependencies of rails and commands like rails s or rails c will work without bundle exec.
I have the gist of the difference between rvm and bundler. On my local machine, I use rvm to manage different rubies and different gemsets for those rubies. For example I have a ruby 2.1.2 with a gemset called core:
$ rvm-prompt
ruby-2.1.2#core
$ rvm gemdir
/Users/donato/.rvm/gems/ruby-2.1.2#core
$ cd /Users/donato/.rvm/gems/ruby-2.1.2#core/gems
$ ls
actionmailer-4.1.10
...
As you can see, I have a ruby 2.1.2 and a gemset core for that ruby. When I run my project, rails looks for the gems located in /Users/donato/.rvm/gems/ruby-2.1.2#core/gems. It DOES NOT look for the gems at shared/bundle. In fact, I don't even have a shared directory at my Rails root in my local machine.
So on my local machine, while bundler manages gem dependencies and adds gems if new ones found in Gemfile, it does not manage the LOCATION of the gems' installation. It installs the gems in rvm gemdir. In fact, when you run bundle install and a new gem exists in Gemfile, then bundler actually installs the gem in rvm's gem directory.
What's confusing is that this is not how it works in staging or production deploy. It appears bundler looks for gems in the location shared/bundle. So apparently in production, bundler not only wants to install the gems, but it wants to manage the location of the gems as well, and let rvm just worry about rubies, but not gem locations.
This has caused an issue for me. I am using capistrano for deployment. When I run cap staging deploy, It is installing gems in the wrong ruby.
The capistrano script runs this line:
Running /usr/local/rvm/bin/rvm ruby-2.1.2#core do bundle install
--path /var/www/mysite_staging/shared/bundle --without development test --deployment --quiet
You can see that it installs the gems in shared/bundle.
When I go to shared/bundle/ruby after a successful deployment, I see the following directory:
/shared/bundle/ruby/2.1.0
Wait a second! In my capistrano 3 script, which is using capistrano-rvm, I specified the following:
set :rvm_type, :system
set :rvm_ruby_version, 'ruby-2.1.2#core'
If it is recommended to use bundler to manage gem locations in staging and production, at shared/bundle directory, then how should I resolve this issue? Why is bundler installing gems in the wrong ruby version for this project?
so, what would you say the major the difference between your machine and the server you are deploying on?
Look at: http://bundler.io/v1.9/deploying.html
See different behaviour beween dev and deployment and also read note on capistrano.
hope this helps
I'm going through Micharl Hartl's well known Rails tutorial, and this piece is confusing me. Every time a new app is set up, these commands are run:
$ bundle install --without production
$ bundle update
$ bundle install
I don't really get why install is being run twice. What is the effect of these three commands run in this sequence?
You should not have to run bundle install twice as bundle update will also install all of your gems (as well as updating them to their most current version). I have not read the tutorial you mentioned but perhaps the purpose of the second install is to install all of the gems, including those reserved for production.
Your second question, what is the effect of these three commands:
bundle install --without production
Inspect the gemfile, ignoring gems that are reserved for production
Resolve all dependencies
Install all gems and dependent gems
Save the exact version of each gem to Gemfile.lock
bundle update
Inspect the gemfile
Resolve all dependencies from scratch using the newest version of each gem and completely ignoring Gemfile.lock
Install all gems and dependent gems
Save the exact version of each gem to Gemfile.lock
bundle install
Because this is the first run of the production gems, inspect the gemfile and resolve dependencies of the production gems
Use Gemfile.lock for exact versions of all other gems to be installed
Install all gems and dependent gems
Save the exact version of each gem to Gemfile.lock
Hoped this helped, for more detailed info about the two commands check out this and this.
$ bundle install --without production prevents bundler from installing any of the production gems. It also gets saved in your local repository and you don't have to run it more than once. Any subsequent run of bundle install will include --without production.
bundle install installs only the missing gems from your Gemfile, while bundle update updates/installs every single gem to the latest version as specified in the GemFile..
When I run bundle install it is not installing gem of production group.
Some day ago I have run bundle install --without production. But Now I want to install gem of production also. How can I install gem with production also.
I believe once you run the bundler using --without production it remembers that setting in the config. So you should be able to undo it by changing the config per the bundle config command.
It seems when I run bundle package then bundle install --local then I run unicorn_rails, unicorn is still accessing system gems. I keep getting :
You have already activated rack 1.5.2, but your Gemfile requires rack
1.2.8. Using bundle exec may solve this.
And it shouldn't because rack 1.2.8 is in the vendor/cache.
bundle exec wont work because it seems to be a resource hog and the whole point of bundle package is avoid this whole mess in the first place.
So how do I get unicorn to get bundle environment to only use the vendor/cache gems?
bundle install --local takes gems in vendor/local and installs them using whatever your default gem command does. By default, that is a system-wide install. If you're using RVM or something else, it'll be in your current RVM gemset.
If you're installing in production, and you want to limit the app to your gems from vendor/local, you want to do bundle install --deployment. This will install the gems into vendor/bundle and set Bundler up to use those gems (and only those gems, not the system ones). If the gems aren't in vendor/local, it will download them. It won't update your Gemfile.lock, and best practice is to keep all your gems in vendor/cache up to date to prevent it from even trying to download gems.
You don't need to use bundle exec unless you're running a binary from one of the gems. If you're running rails server and having this problem, the reason is that the rails command is running from the shell's $PATH. It's presumably a different version of Rails than the one you'd like to use.
If that's the case, your options are to track down the path to the version of rails you want and run it explicitly, to use bundle exec, or to run bundle install --binstubs --deployment and add that bin directory to your PATH. I haven't noticed any overhead from bundle exec, but if you're concerned about that and still want to scope everything to your bundle, then use --binstubs (this is how Heroku does it, by the way).