Bundle Package and Deployment
Hi all,
New user to the Gorails site, what a fantastic resource! I'll be upgrading to Pro shortly.
I have a first question (probably of many)...
I am deploying my app with Capistrano and it works perfectly, I'm very happy with the setup. However, I'm unsure of how Bundle / Gems are working on the production server.
I ran Bundle Package on my development machine when I first deployed and so gems are in Vendor/Cache. Now everytime I deploy gems don't seem to get installed on the production server, which is fine but I wondered if someone can tell me in more detail how Bundle Package works and how the production app is referencing the bundled gems?
For example, if I login to the production server and try running rails c, I receive the "The program 'rails' is currently not installed." message. So my app must be using gems within the vendor/cache folder.
Thanks.
Hey Philip,
Capistrano just runs bundle
on the server. You can see it in the logs.
Gems can be installed in different folders, and Capistrano will cache the gems in a shared bundle folder in your repo's folder on the server. It can also load gems from outside that like the vendor folder or gems installed on the user or system level.
For some reason, I'm getting the same issue with Capistrano. If I add a new gem, it'll run the bundle command but it won't be installed on the server. I don't know why that is. It's caused GoRails to crash a couple times because of that.
We probably need to poke around the issues on Github to see if there's anyone else mentioning the issue: https://github.com/capistrano/bundler.
Also on the server, your gems won't necessarily be in your PATH, so you may have to run bundle exec rails c
to run the Rails console.
Philip,
edit
Looks like while I was typing Chris responded, defer to that answer.
First of all, welcome, I have been a pro memeber for over 4 years now, you will love the community and gain TONS of value from the pro episodes, highly recommend the upgrade.
I think I can help with some of these questions.
Are you using the 'capistrano-bundler' gem? Is this included in your Capfile
? Note that '.bundle' should be added to the linked_dirs
array in the deploy.rb
file per the capistrano-bundler gem's readme. If this isn't your issue, it may be beneficial to paste your capfile and deploy.rb files.
Next, I believe your issue with running rails console on the prod server is that you need to change directories to the current folder of your app, where rails would be installed and also use the production environment variable. If you follow the GoRails guides for deploment, that would look llike this:
- ssh deploy@1.2.3.4
- cd my-app-name/current/
- RAILS_ENV=production bundle exec rails c
Once in the proper directory, and you set the env for the command, you should be able to access the console as you expect. Hopefully this helps!
Thanks for the answers guys (although) a little over my head I'm afraid, so I'll dig around.
Everything is working fine (except the console side of things, but I think your answer Thomas is getting me a step closer to that working).
I was just wondering how the Rails app was running because as far as I can tell my gems are just in vendor/cache and nowhere else. I'm presuming Rails references them from there somehow?
Thomas, yes I am using 'capistrano-bundler' and it is in my Capfile.
My linked_dirs line is actually commented out: append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
Chris, I do have a bundle folder in my shared folder on the server which then contains ruby/2.5.0/gems/...
I guess what I am saying is, when deploying gems aren't being installed in the same fashion as on the development machine.
I use RVM on both development and production. In development the gems are installed into .rvm/....
I presumed when running capistrano it would run bundle install which would install the gems into .rvm/.... on the production server. This doesn't seem to be the case.
This has also helped answer another question I had, I wasn't able to run rake db:seed but running RAILS_ENV=production bundle exec rake db:seed worked a treat.
Now to work out how to write a Capistrano task to run that.
Yes, any rake / rails command you would run locally can be run in that fashion on prod.
Typically you wouldn't want to seed the database on every single deploy, unless you have some special circumstance. In my experience db:seed is a one-off-task, typically reserved for initial setup. I run the command, just as you have above, a single time to get my database inline.
After initial setup, the database will still contain this data no matter how many future deploys you have. Does that make sense? I could of course be missing something if you have a unique set up.
Thanks Thomas, yes it makes sense. I'm using it essentialy to create my user account. I'm only building a simple blog for myself at this point and don't want to allow registrations so only 1 user is required.
I'd like to see if I can write a task to do it, I'll probably remove the task but for learning purposes I'd like to write one.
Having trouble though, maybe you can help. Running RAILS_ENV=production bundle exec rake db:seed within the 'current' directory works fine but it I write a task such as:
desc "reload the database with seed data"
task :seed do
on roles :all do
within current_path do
execute "RAILS_ENV=production bundle exec rake db:seed"
end
end
end
I'm getting the error: bash: bundle: command not found
I'm not sure why.
I think you need to use Capistrano's rake helper. Try replacing your execute
line with:
with rails_env: "#{fetch(:stage)}" do
execute :rake, "db:create"
end
They have a bunch of docs, but there's some details on the nuances here: https://capistranorb.com/documentation/getting-started/tasks/
Chris, you beat me to it, from digging into the migration tasks I found the rake helper and did this:
desc 'Runs rake db:seed'
task :seed do
on roles :all do
within current_path do
execute :rake, 'db:seed RAILS_ENV=production'
end
end
end
I need to tidy it up to fetch the environment as per your example.
Also, I did find that when capistrano runs bundler:install it appears to be installed gems into the shared/bundle folder:
~/.rvm/bin/rvm 2.5.0 do bundle install --path /var/www/deploy/APP/shared/bundle --without deve…
The fetch environment is useful because when you run cap production deploy
it'll use production from there. And then it seamlessly supports cap staging deploy
if you add a staging environment. 🙌
And yeah, it installs the gems inside the app folder, that way if you had multiple apps on the server, you wouldn't crash one if removing the other accidentally removed gems or something.
I still have the issue of adding new gems, but I haven't looked too hard to find a solution for it myself.