简体   繁体   English

在亚马逊 EC2 上使用 capistrano 部署到生产环境时,资产不会预编译

[英]Assets won't precompile when deploying with capistrano to production on amazon EC2

I worked on being able to deploy to production using capistrano.我致力于能够使用 capistrano 部署到生产环境。 I face several issues and while fixing most of them we still have a last one.我面临着几个问题,在解决其中大部分问题的同时,我们还有最后一个。

Our precompile assets options are not properly compiling them on production and because of that, we are unable to use the last developed features as they rely heavily on JS.我们的预编译资产选项没有在生产中正确编译它们,因此,我们无法使用上次开发的功能,因为它们严重依赖于 JS。

Without trying to influence on how anyone would analyze this problem, this is some of what I did trying to make it work:在不试图影响任何人如何分析这个问题的情况下,这是我为使其工作所做的一些努力:

  1. Precompiled assets locally, pushed to github repo, cap deployed from local machines to ec2.在本地预编译资产,推送到 github repo,从本地机器部署到 ec2。 cap deploy is local, the code being pushed to ec2 is the one on github. cap deploy是本地的,推送到ec2的代码是github上的。
  2. Tried using capistrano tasks as suggested.按照建议尝试使用 capistrano 任务。 Using load 'deploy'assets' in the Capfile and letting the cap deploy:setup task do its thing.在 Capfile 中使用 load 'deploy'assets' 并让 cap deploy:setup 任务完成它的工作。
  3. Used the option cap deploy:assets:clean and then cap deploy:assets:precompile使用选项 cap deploy:assets:clean 然后 cap deploy:assets:precompile
  4. Tried removing assets from public and then use a pipeline_precompile task in deploy.rb尝试从 public 中删除资产,然后在 deploy.rb 中使用 pipeline_precompile 任务
  5. Expired assets, forcing rails to precompile everything changing assets.versions in application.rb过期资产,强制 Rails 预编译所有更改 application.rb 中的 assets.versions
  6. Tried different combinations on config.assets in environments/production.rb在environments/production.rb 中的config.assets 上尝试了不同的组合
  7. Finally, tried deleting public/assets in production and precompiling up there using RAILS_ENV=production bundle exec rake assets:precompile最后,尝试删除生产中的公共/资产并使用 RAILS_ENV=production bundle exec rake assets:precompile 在那里进行预编译

The app is just not using the new JS files.该应用程序只是不使用新的 JS 文件。 If you check the code either on the repo or in the server itself, I introduced a simple comment to the name.js.coffee ("# Shows and hides menus depending on the data on DB" on line xxx) and this is not in the compiled assets.js in production.如果您在 repo 或服务器本身中检查代码,我在 name.js.coffee 中引入了一个简单的注释(“#根据 DB 上的数据显示和隐藏菜单”在第 xxx 行),这不在在生产中编译的 assets.js。 This is a quick test to be sure the recent assets are being used.这是一个快速测试,以确保正在使用最近的资产。

The whole problem here is the js and css files, not so much rails.这里的整个问题是 js 和 css 文件,而不是 Rails。 Which is why it is so difficult to test or find.. Thus one of the reasons for the popularity of js frameworks lately.这就是为什么测试或发现如此困难的原因..这也是最近js框架流行的原因之一。 In case of problems, you don't have to kill yourself looking for where the problem is.. If the prob is in ruby or rails, usually doesn't take that long to find out.万一出现问题,您不必为了寻找问题出在何处而绞尽脑汁。 Once you get to js, css and cross browser compatibility, well, this IS the problem at hand.一旦您了解 js、css 和跨浏览器兼容性,那么,这就是手头的问题。

Here's my deploy.rb file.这是我的 deploy.rb 文件。 Running rails 3.2.12 ruby-1.9.3-p327:运行导轨 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

On-working new/alternative (deploy_new2.rb) file:正在运行的新/替代 (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"

And ./Capfile:和 ./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

Thank you in advance for any help!预先感谢您的任何帮助! Let me know if you need more info.如果您需要更多信息,请告诉我。

You don't need your own :precompile_assets task.您不需要自己的 :precompile_assets 任务。 You are using Capistrano's by including load 'deploy/assets' in your Capfile.您通过在 Capfile 中包含加载“部署/资产”来使用 Capistrano。

Removing the :precompile_assets task from your deploy.rb may resolve the issue.从您的 deploy.rb 中删除 :precompile_assets 任务可能会解决该问题。 If you look at the source code for Capistrano, you'll see it implements :precompile_assets quite differently: https://github.com/capistrano/capistrano/blob/legacy-v2/lib/capistrano/recipes/deploy/assets.rb如果您查看 Capistrano 的源代码,您会看到它实现 :precompile_assets 的方式完全不同: https : //github.com/capistrano/capistrano/blob/legacy-v2/lib/capistrano/recipes/deploy/assets.rb

You can try this code你可以试试这个代码

# 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"

Solution: Here's the working deploy 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, "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"

I found that the capistrano asset compile rules got run before the bundler rules, so nothing worked, I wrote my own:我发现 capistrano 资产编译规则在打包规则之前运行,所以没有任何效果,我自己写了:

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

I then found that I really wasn't interested in installing a js runtime on my production machines.然后我发现我真的对在我的生产机器上安装 js 运行时不感兴趣。 I went back to just putting my assets into a deploy branch of my git tree.我回到只是将我的资产放入我的 git 树的部署分支。 First time I did this, I forgot to include the manifest.yml file.我第一次这样做时,忘记包含 manifest.yml 文件。

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

If you have uglifier in Gemfile, which runs during asset compilation, it may have been configured to remove just the sort of comment you are using as a test for whether the changed Javascript assets are being deployed.如果您在 Gemfile 中有 uglifier,它在资产编译期间运行,它可能已配置为仅删除您用作测试是否正在部署更改的 Javascript 资产的那种注释。

Uglifier's Readme says this is possible, and distinguishes several kinds of comments. Uglifier 的自述文件这是可能的,并区分了几种评论。 So it's possible you may have been misled by seeing another comment still remaining after asset compilation.因此,您可能会因为在资产编译后看到另一条评论仍然存在而被误导。

Another clue to judging this possibility is that (as you say) this problem arose after a long (tiring) process of fixing other problems.判断这种可能性的另一个线索是(如您所说)这个问题是在解决其他问题的长期(累人)过程之后出现的。 Often, this can block people from a perception like this;通常,这会阻止人们产生这样的看法; a long effort can 'lock them in' to an assumption.长期的努力可以将他们“锁定”在一个假设中。

So, try adding a variable declaration instead of a comment, in your Javascript.因此,尝试在您的 Javascript 中添加变量声明而不是注释。

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

I encountered this problem.我遇到了这个问题。 Turns out I had to install node and yarn on my servers for rake assets:precompile to work原来我必须在我的服务器上安装 node 和 yarn 以获得 rake 资产:预编译才能工作

I also had this issue recently, asset precompilation with Capistrano deployment was hanging in AWS.我最近也遇到了这个问题,使用 Capistrano 部署的资产预编译挂在 AWS 中。 I solved the issue by switching from a t3.micro instance to a t3.small instance temporarily while I deployed.我通过在部署时暂时从 t3.micro 实例切换到 t3.small 实例解决了这个问题。 It looks like the micro instance did not have enough resources for the precompilation step.看起来微实例没有足够的资源用于预编译步骤。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM