在亚马逊EC2上使用capistrano进行生产时,资产不会预编译

时间:2013-03-23 00:15:36

标签: ruby-on-rails deployment amazon-ec2 capistrano asset-pipeline

我致力于使用capistrano部署到生产中。我面临几个问题,在解决大多数问题的同时,我们还有最后一个问题。

我们的预编译资产选项在生产时没有正确编译它们,因此,我们无法使用最后开发的功能,因为它们严重依赖JS。

不试图影响任何人如何分析这个问题,这是我尝试使其发挥作用的一部分:

  1. 本地预编译资产,推送到github repo,从本地计算机部署到ec2。 cap deploy是本地的,被推送到ec2的代码是github上的代码。
  2. 按照建议尝试使用capistrano任务。在Capfile中使用load'debloy'assets'并让cap deploy:setup task做它的事情。
  3. 使用选项cap deploy:assets:clean然后cap deploy:assets:precompile
  4. 尝试从public中删除资产,然后在deploy.rb
  5. 中使用pipeline_precompile任务
  6. 过期资产,强制rails预编译application.rb
  7. 中所有更改assets.versions的内容
  8. 在environment / production.rb
  9. 中的config.assets上尝试了不同的组合
  10. 最后,尝试删除生产中的公共/资产,并使用RAILS_ENV =生产包exec rake资产进行预编译:预编译
  11. 该应用程序只是没有使用新的JS文件。如果您在repo或服务器本身检查代码,我在name.js.coffee中引入了一个简单的注释(“显示和隐藏菜单,具体取决于数据库上的数据”,这是在xxx行),这不是生产中编译的assets.js。这是一个快速测试,以确保最近的资产被使用。

    这里的问题是js和css文件,而不是rails。这就是为什么它如此难以测试或找到..因此最近js框架普及的原因之一。如果出现问题,你不必自杀,寻找问题所在。如果问题是红宝石或铁轨,通常不需要那么长时间才能发现。一旦你获得了js,css和跨浏览器的兼容性,那么这就是问题所在。

    这是我的deploy.rb文件。运行轨道3.2.12 ruby​​-1.9.3-p327:

    # $:.unshift(File.expand_path('./lib', ENV['rvm_path']))
    
    # Load rvm's capistrono plugins
    require 'rvm/capistrano'
    
    require 'bundler/capistrano'
    
    set :rvm_type, :user
    
    set :user, 'username'
    set :domain, 'ip_address'
    set :application, "app_pro"
    set :keep_releases, 2 # It keeps on two old releases.
    
    # git repo details
    set :scm, :git # You can set :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
    set :repository,  "git@github.com:user/app.git"
    set :scm_username, 'user'
    set :git_enable_submodules, 1
    set :git_shallow_clone, 1
    set :branch, 'master'
    
    # Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
    
    
    role :web, domain                          # Your HTTP server, Apache/etc
    role :app, domain                          # This may be the same as your `Web` server
    role :db,  domain, :primary => true# 'ec2-23-23-156-118.compute-1.amazonaws.com' This is where Rails migrations will run
    # role :db,  "your slave db-server here"
    
    # deply options
    default_run_options[:pty] = true
    set :ssh_options, {:forward_agent => true}
    set :ssh_options, {:auth_methods => "publickey"}
    set :ssh_options, {:keys => ["~/Downloads/key.pem"]}
    set :deploy_to, "/home/user/appdir"
    set :deploy_via, :remote_cache
    set :use_sudo, false
    
    # if you want to clean up old releases on each deploy uncomment this:
    after "deploy:restart", "deploy:cleanup"
    
    # if you're still using the script/reaper helper you will need
    # these http://github.com/rails/irs_process_scripts
    
    # If you are using Passenger mod_rails uncomment this:
    namespace :deploy do
      task :start do
        # run COMMAND="/etc/init.d/nginx restart" invoke SUDO=1
        run "sudo /etc/init.d/nginx restart"
        # exit
      end
      after "deploy:start", "deploy:cleanup"
    
      task :stop do ; end
      task :restart, :roles => :app, :except => { :no_release => true } do
        run "touch #{File.join(current_path,'tmp','restart.txt')}"
      end
    
      task :setup_config, roles: :app do
        run "mkdir -p #{shared_path}/config"
        put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml"
        puts 'now edit the config file database in #{shared_path}'
      end
      after 'deploy:setup', 'deploy:setup_config'
    
      desc "Symlink shared resources on each release - not used"
      task :symlink_config, :roles => :app do
        run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
      end
    
      after 'deploy:finalize_update', 'deploy:symlink_config'
    
      desc "It helps to seed database with values"
      task :seed do
        run "cd #{current_path}; bundle exec rake db:seed RAILS_ENV=#{rails_env}"
      end
      task :create_schema do
        run "cd #{current_path}; bundle exec rake db:create RAILS_ENV=#{rails_env} --trace"
      end
    end
    

    正在运行的新/替代(deploy_new2.rb)文件:

    # On-working new/alternative deploy.rb file:
    
    require 'rvm/capistrano'
    require 'bundler/capistrano'
    
    set :rvm_type, :user
    
    set :application, "ip_address"
    set :domain, 'ip_address'
    
    # Roles
    role :web, domain
    role :app, domain
    role :db,  domain, :primary => true
    
    #deployment details
    set :deploy_via, :remote_cache
    set :user, "username"
    set :copy_compression, :bz2
    set :git_shallow_clone, 1
    set :scm_verbose, true
    set :use_sudo, false
    set :deploy_to, "/home/user/dir"
    
    default_run_options[:pty] = true
    set :ssh_options, {:forward_agent => true}
    set :ssh_options, {:auth_methods => "publickey"}
    set :ssh_options, {:keys => ["~/Downloads/key.pem"]}
    
    #repo details
    set :scm, :git
    set :repository,  "git@github.com:user/app.git"
    set :scm_username, 'user'
    set :keep_releases, 2
    set :branch, "master"
    
    
    namespace :deploy do
      # task :start, :roles => :app, :except => { :no_release => true } do
      #   # not need to restart nginx every time
      #   # run "service nginx start"
      #   run "cd #{release_path} && touch tmp/restart.txt"
      # end
    
      # after "deploy:start", "deploy:cleanup"
      # after 'deploy:cleanup', 'deploy:symlink_config'
    
      # You do not need reload nginx every time, eventhought if you use passenger or unicorn
      # task :stop, :roles => :app, :except => { :no_release => true } do
      #   run "service nginx stop"
      # end
    
      # task :graceful_stop, :roles => :app, :except => { :no_release => true } do
      #   run "service nginx stop"
      # end
    
      # task :reload, :roles => :app, :except => { :no_release => true } do
      #   run "cd #{release_path} && touch tmp/restart.txt"
      #   run "service nginx restart"
      # end
    
      task :restart, :roles => :app, :except => { :no_release => true } do
        run "cd #{release_path} && touch tmp/restart.txt"
      end
    
      # If you enable assets/deploy in Capfile, you do not need this
      # task :pipeline_precompile do
      #   # run "cd #{release_path}; RAILS_ENV=#{rails_env} bundle exec rake assets:precompile"
      #   # precompile assets before deploy and upload them to server 
      #   # run_locally("RAILS_ENV=#{rails_env} rake assets:clean && RAILS_ENV=#{rails_env} rake assets:precompile")
      #   # top.upload "public/assets", "#{release_path}/public/assets", :via =>:scp, :recursive => true
      # end
    end
    
    # you do not need to this, because you already add require 'bundler/capistrano'
    # before "deploy:assets:precompile", "bundle:install"
    

    和./Capfile:

    load 'deploy'
    # Uncomment if you are using Rails' asset pipeline
    load 'deploy/assets'
    load 'config/deploy' # remove this line to skip loading any of the default tasks
    

    提前感谢您的帮助!如果您需要更多信息,请告诉我。

7 个答案:

答案 0 :(得分:13)

您不需要自己的:precompile_assets任务。您通过在Capfile中加载'deploy / assets'来使用Capistrano。

从deploy.rb中删除:precompile_assets任务可能会解决此问题。如果你看一下Capistrano的源代码,你会发现它实现了:precompile_assets完全不同:https://github.com/capistrano/capistrano/blob/legacy-v2/lib/capistrano/recipes/deploy/assets.rb

答案 1 :(得分:1)

您可以尝试此代码

# On-working new/alternative deploy.rb file:

require 'rvm/capistrano'
require 'bundler/capistrano'

set :rvm_type, :user

set :application, "ip_address"
set :domain, 'ip_address'

# Roles
role :web, domain
role :app, domain
role :db,  domain, :primary => true

#deployment details
set :deploy_via, :remote_cache
set :user, "username"
set :copy_compression, :bz2
set :git_shallow_clone, 1
set :scm_verbose, true
set :use_sudo, false
set :deploy_to, "/home/user/dir"

default_run_options[:pty] = true
set :ssh_options, {:forward_agent => true}
set :ssh_options, {:auth_methods => "publickey"}
set :ssh_options, {:keys => ["~/Downloads/key.pem"]}

#repo details
set :scm, :git
set :repository,  "git@github.com:user/app.git"
set :scm_username, 'user'
set :keep_releases, 2
set :branch, "master"


namespace :deploy do
  # task :start, :roles => :app, :except => { :no_release => true } do
  #   # not need to restart nginx every time
  #   # run "service nginx start"
  #   run "cd #{release_path} && touch tmp/restart.txt"
  # end

  # after "deploy:start", "deploy:cleanup"
  # after 'deploy:cleanup', 'deploy:symlink_config'

  # You do not need reload nginx every time, eventhought if you use passenger or unicorn
  # task :stop, :roles => :app, :except => { :no_release => true } do
  #   run "service nginx stop"
  # end

  # task :graceful_stop, :roles => :app, :except => { :no_release => true } do
  #   run "service nginx stop"
  # end

  # task :reload, :roles => :app, :except => { :no_release => true } do
  #   run "cd #{release_path} && touch tmp/restart.txt"
  #   run "service nginx restart"
  # end

  task :restart, :roles => :app, :except => { :no_release => true } do
    run "cd #{release_path} && touch tmp/restart.txt"
  end

  # If you enable assets/deploy in Capfile, you do not need this
  # task :pipeline_precompile do
  #   # run "cd #{release_path}; RAILS_ENV=#{rails_env} bundle exec rake assets:precompile"
  #   # precompile assets before deploy and upload them to server 
  #   # run_locally("RAILS_ENV=#{rails_env} rake assets:clean && RAILS_ENV=#{rails_env} rake assets:precompile")
  #   # top.upload "public/assets", "#{release_path}/public/assets", :via =>:scp, :recursive => true
  # end
end

# you do not need to this, because you already add require 'bundler/capistrano'
# before "deploy:assets:precompile", "bundle:install"

答案 2 :(得分:1)

解决方案:这是工作部署文件 -

require 'rvm/capistrano'
require 'bundler/capistrano'

set :rvm_type, :user

set :application, "ip_address"
set :domain, 'ip_address'

# Roles
role :web, domain
role :app, domain
role :db,  domain, :primary => true

#deployment details
set :deploy_via, :remote_cache
set :user, "user"
set :copy_compression, :bz2
set :git_shallow_clone, 1
set :scm_verbose, true
set :use_sudo, false
set :deploy_to, "/home/user/app_dir"

default_run_options[:pty] = true
set :ssh_options, {:forward_agent => true}
set :ssh_options, {:auth_methods => "publickey"}
set :ssh_options, {:keys => ["~/sites/app/config/key.pem"]}

#repo details
set :scm, :git
set :repository,  "git@github.com:github_id/app.git"
set :scm_username, 'github_id'
set :keep_releases, 2
set :branch, "master"

after 'deploy:update_code', 'deploy:symlink_db'

namespace :deploy do
  # task :start, :roles => :app, :except => { :no_release => true } do
  #   # not need to restart nginx every time
  #   # run "service nginx start"
  #   run "cd #{release_path} && touch tmp/restart.txt"
  # end

  # after "deploy:start", "deploy:cleanup"
  # after 'deploy:cleanup', 'deploy:symlink_config'

  # You do not need reload nginx every time, eventhought if you use passenger or unicorn
  # task :stop, :roles => :app, :except => { :no_release => true } do
  #   run "service nginx stop"
  # end

  # task :graceful_stop, :roles => :app, :except => { :no_release => true } do
  #   run "service nginx stop"
  # end

  # task :reload, :roles => :app, :except => { :no_release => true } do
  #   run "cd #{release_path} && touch tmp/restart.txt"
  #   run "service nginx restart"
  # end

  task :restart, :roles => :app, :except => { :no_release => true } do
    run "cd #{release_path} && touch tmp/restart.txt"
  end

  desc "Symlinks the database.yml"
  task :symlink_db, :roles => :app do
    run "ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
  end

  # If you enable assets/deploy in Capfile, you do not need this
  # task :pipeline_precompile do
  #   # run "cd #{release_path}; RAILS_ENV=#{rails_env} bundle exec rake assets:precompile"
  #   # precompile assets before deploy and upload them to server 
  #   # run_locally("RAILS_ENV=#{rails_env} rake assets:clean && RAILS_ENV=#{rails_env} rake assets:precompile")
  #   # top.upload "public/assets", "#{release_path}/public/assets", :via =>:scp, :recursive => true
  # end
end

# you do not need to this, because you already add require 'bundler/capistrano'
# before "deploy:assets:precompile", "bundle:install"

答案 3 :(得分:1)

我发现capistrano资产编译规则在捆绑器规则之前运行,所以没有任何工作,我写了自己的:

  after "bundle:install" do
    run "cd #{release_path}; RAILS_ENV=production bundle exec rake assets:precompile"
  end

然后我发现我真的对在我的生产机器上安装js运行时不感兴趣。我回过头来把我的资产放到我的git树的deploy分支中。 我第一次这样做,我忘了包含manifest.yml文件。

http://jimneath.org/2012/05/05/precompile-assets-using-a-git-hook.html

答案 4 :(得分:0)

如果您在资产编译期间运行的Gemfile中有uglifier,则可能已将其配置为仅删除您用于评估是否正在部署已更改的Javascript资产的注释。

Uglifier的自述文件says这是可能的,并区分了几种注释。因此,有可能在资产编制后看到另一条评论仍未被误导。

判断这种可能性的另一个线索是(如你所说)这个问题是在解决其他问题的漫长(累人)过程之后产生的。通常,这可以阻止人们这样的感知;长期的努力可以“锁定”他们的假设。

因此,请尝试在Javascript中添加变量声明而不是注释。

答案 5 :(得分:0)

我遇到了与此类似的问题,但是解决方案是删除Gemfile中的资产组,因为用于预编译的默认任务上限取决于看似不在单独组中的资产。

答案 6 :(得分:0)

我遇到了这个问题。事实证明,我必须在服务器上安装节点和yarn才能获得rake资产:预编译才能正常工作