capistrano - Why do I need to precompile Rails assets on app servers and not web servers only? -
i'm deploying simple rails app small ubuntu precise64 server setup :
* 1 web server running nginx
* 2 app servers running unicorn
* 1 db server running postgresql
my servers provisionned puppet , i'm pushing app capistrano.
my capfile
load 'deploy' # uncomment if using rails' asset pipeline load 'deploy/assets' load 'config/deploy' # remove line skip loading of default tasks
the deploy.rb file super simple
# execute "bundle install" after deploy, when needed require "bundler/capistrano" # name of application in scm (git) set :application, "devops-test-app" set :repository, "https://github.com/geoffroymontel/devops-test-app.git" set :scm, :git set :deploy_to, "/var/www/#{application}" # server there web server running (nginx) role :web, "172.16.0.2" # server there db running # rails migrations run role :db, "172.16.0.3", :primary => true # servers there app servers running (unicorn) role :app, "172.16.0.4", "172.16.0.5" set :rails_env, :production # user on server set :user, "deployer" set :use_sudo, false namespace :deploy task :start, :roles => :app, :except => { :no_release => true } run "service unicorn_#{application} start" end task :stop, :roles => :app, :except => { :no_release => true } run "service unicorn_#{application} stop" end task :restart, :roles => :app, :except => { :no_release => true } run "service unicorn_#{application} restart" end task :copy_in_database_yml run "cp #{shared_path}/config/database.yml #{latest_release}/config/" end # precompile assets # have precompile assets on app servers too, , don't know why... # namespace :assets # task :precompile, :roles => [:web, :app], :except => { :no_release => true } # run %q{cd #{latest_release} && #{rake} rails_env=#{rails_env} #{asset_env} assets:precompile} # end # end end before "deploy:assets:precompile", "deploy:copy_in_database_yml"
if don't precompile assets on app servers, application fails.
$ cap roles="app" command="cat /var/www/devops-test-app/current/log/production.log" invoke * 2013-05-01 21:43:10 executing `invoke' * executing "cat /var/www/devops-test-app/current/log/production.log" servers: ["172.16.0.4", "172.16.0.5"] [172.16.0.5] executing command ** [out :: 172.16.0.5] connecting database specified database.yml ** [out :: 172.16.0.5] connecting database specified database.yml ** [out :: 172.16.0.5] started "/posts" 172.16.0.2 @ 2013-05-01 19:42:10 +0000 ** [out :: 172.16.0.5] processing postscontroller#index html ** [out :: 172.16.0.5] rendered posts/index.html.erb within layouts/application (25.7ms) ** [out :: 172.16.0.5] completed 500 internal server error in 122ms ** [out :: 172.16.0.5] ** [out :: 172.16.0.5] actionview::template::error (application.css isn't precompiled): ** [out :: 172.16.0.5] 2: <html> ** [out :: 172.16.0.5] 3: <head> ** [out :: 172.16.0.5] 4: <title>devopstestapp</title> ** [out :: 172.16.0.5] 5: <%= stylesheet_link_tag "application", :media => "all" %> ** [out :: 172.16.0.5] 6: <%= javascript_include_tag "application" %> ** [out :: 172.16.0.5] 7: <%= csrf_meta_tags %> ** [out :: 172.16.0.5] 8: </head> ** [out :: 172.16.0.5] app/views/layouts/application.html.erb:5:in `_app_views_layouts_application_html_erb__677166568443748084_17536100' ** [out :: 172.16.0.5] app/controllers/posts_controller.rb:7:in `index'
if uncomment commented lines in deploy.rb
, fine.
but why ?? thought need compile assets on web server, not on app server.
please me understand why :)
thanks, best regards
geoffroy
because, among other things, rails generates manifest of precompiled assets including hashes of files in filenames, , uses names when include assets in page. when image_url('foo.jpg')
, rails end generating foo-b48cf0140bea12734db05ebcdb012f1d265bed84.jpg
in source code.
rails needs know compiled names use these assets, has have manifest, precompilation needs done on app server.
take @ public/assets/manifest.yml
- that's file rails needs in order serve precompiled assets properly.
Comments
Post a Comment