如何使用Chef预编译资产?

时间:2013-06-11 20:44:13

标签: ruby-on-rails chef aws-opsworks

OpsWorks不会在部署时预编译资产。我在this thread中找到了这个食谱,但我认为它不完整,或遗漏了一些东西,因为我收到的错误是release_path未找到。

precompile.rb:

Chef::Log.info("Running deploy/before_migrate.rb...")

Chef::Log.info("Symlinking #{release_path}/public/assets to #{new_resource.deploy_to}/shared/assets")

link "#{release_path}/public/assets" do
  to "#{new_resource.deploy_to}/shared/assets"
end

rails_env = new_resource.environment["RAILS_ENV"]
Chef::Log.info("Precompiling assets for RAILS_ENV=#{rails_env}...")

execute "rake assets:precompile" do
  cwd release_path
  command "bundle exec rake assets:precompile"
  environment "RAILS_ENV" => rails_env
end

日志

undefined local variable or method `release_path' for ....

有什么想法吗?我根本不认识厨师,我正在努力解决这个问题。

4 个答案:

答案 0 :(得分:10)

在OpsWorks开箱即用支持Asset Pipeline之前,您可以这样做。 在rails应用程序中创建一个包含以下内容的文件deploy/before_symlink.rb

run "cd #{release_path} && RAILS_ENV=production bundle exec rake assets:precompile"

如果将Rails应用程序部署到其他环境,请更改RAILS_ENV。

如果您使用NGINX / Unicorn堆栈,则必须修改/assets资源。 只需将以下内容复制到食谱中名为unicorn/templates/default/nginx_unicorn_web_app.erb的文件中即可。

upstream unicorn_<%= @application[:domains].first %> {
 server unix:<%= @application[:deploy_to]%>/shared/sockets/unicorn.sock fail_timeout=0;
}

server {
  listen 80;
  server_name <%= @application[:domains].join(" ") %> <%= node[:hostname] %>;
  access_log <%= node[:nginx][:log_dir] %>/<%= @application[:domains].first %>.access.log;

  keepalive_timeout 5;

  root <%= @application[:absolute_document_root] %>;

  <% if @application[:nginx] && @application[:nginx][:client_max_body_size] %>
    client_max_body_size <%= @application[:nginx][:client_max_body_size] %>;
  <% end %>

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    # If you don't find the filename in the static files
    # Then request it from the unicorn server
    if (!-f $request_filename) {
      proxy_pass http://unicorn_<%= @application[:domains].first %>;
      break;
    }
  }

  location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
  }

  location ~ ^/assets/ {
    expires 1y;
    add_header Cache-Control public;

    add_header ETag "";
    break;
  }

  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root <%= @application[:absolute_document_root] %>;
  }
}

<% if @application[:ssl_support] %>
server {
  listen   443;
  server_name <%= @application[:domains].join(" ") %> <%= node[:hostname] %>;
  access_log <%= node[:nginx][:log_dir] %>/<%= @application[:domains].first %>-ssl.access.log;

  ssl on;
  ssl_certificate /etc/nginx/ssl/<%= @application[:domains].first %>.crt;
  ssl_certificate_key /etc/nginx/ssl/<%= @application[:domains].first %>.key;
  <% if @application[:ssl_certificate_ca] -%>
  ssl_client_certificate /etc/nginx/ssl/<%= @application[:domains].first %>.ca;
  <% end -%>

  keepalive_timeout 5;

  root <%= @application[:absolute_document_root] %>;

  <% if @application[:nginx] && @application[:nginx][:client_max_body_size] %>
    client_max_body_size <%= @application[:nginx][:client_max_body_size] %>;
  <% end %>

  location / {
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    # If you don't find the filename in the static files
    # Then request it from the unicorn server
    if (!-f $request_filename) {
      proxy_pass http://unicorn_<%= @application[:domains].first %>;
      break;
    }
  }

  location ~ ^/assets/ {
    expires 1y;
    add_header Cache-Control public;

    add_header ETag "";
    break;
  }

  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root <%= @application[:absolute_document_root] %>;
  }
}
<% end %>

如果您使用Apache2 / Passenger堆栈,则必须修改/assets资源。 只需将以下内容复制到食谱中名为 passenger_apache2/templates/default/web_app.conf.erb的文件中即可。

<VirtualHost *:80>
  ServerName <%= @params[:server_name] %>
  <% if @params[:server_aliases] && !@params[:server_aliases].empty? -%>
  ServerAlias <% @params[:server_aliases].each do |a| %><%= "#{a}" %> <% end %>
  <% end -%>

  <% if @params[:mounted_at] -%>
  DocumentRoot /var/www
  <%= @params[:deploy][:passenger_handler] -%>BaseURI <%= @params[:mounted_at] %>
  <% else -%>
  DocumentRoot <%= @params[:docroot] %>
  <%= @params[:deploy][:passenger_handler] -%>BaseURI /
  <% end -%>
  <%= @params[:deploy][:passenger_handler] -%>Env <%= @params[:rails_env] %>

  <Directory <%= @params[:docroot] %>>
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  <Directory ~ "\.svn">
    Order allow,deny
    Deny from all
  </Directory>

  <Directory ~ "\.git">
    Order allow,deny
    Deny from all
  </Directory>

  <LocationMatch "^/assets/.*$">
    Header unset ETag
    FileETag None
    # RFC says only cache for 1 year
    ExpiresActive On
    ExpiresDefault "access plus 1 year"
  </LocationMatch>

  LogLevel info
  ErrorLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-error.log
  CustomLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-access.log combined
  CustomLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-ganglia.log ganglia

  FileETag none

  RewriteEngine On
  Include <%= @params[:rewrite_config] %>*
  RewriteLog <%= node[:apache][:log_dir] %>/<%= @application_name %>-rewrite.log
  RewriteLogLevel 0

  # Canonical host
  #RewriteCond %{HTTP_HOST}   !^<%= @params[:server_name] %> [NC]
  #RewriteCond %{HTTP_HOST}   !^$
  #RewriteRule ^/(.*)$        http://<%= @params[:server_name] %>/$1 [L,R=301]

  RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|jpeg|png)$
  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
  RewriteRule ^.*$ /system/maintenance.html [L]

  Include <%= @params[:local_config] %>*
</VirtualHost>

<% if node[:deploy][@application_name][:ssl_support] -%>
<VirtualHost *:443>
  ServerName <%= @params[:server_name] %>
  <% if @params[:server_aliases] && !@params[:server_aliases].empty? -%>
  ServerAlias <% @params[:server_aliases].each do |a| %><%= "#{a}" %> <% end %>
  <% end -%>

  SSLEngine on
  SSLProxyEngine on
  SSLCertificateFile <%= node[:apache][:dir] %>/ssl/<%= @params[:server_name] %>.crt
  SSLCertificateKeyFile <%= node[:apache][:dir] %>/ssl/<%= @params[:server_name] %>.key
  <% if @params[:ssl_certificate_ca] -%>
  SSLCACertificateFile <%= node[:apache][:dir] %>/ssl/<%= @params[:server_name] %>.ca
  <% end -%>
  SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

  <% if @params[:mounted_at] -%>
  DocumentRoot /var/www
  <%= @params[:deploy][:passenger_handler] -%>BaseURI <%= @params[:mounted_at] %>
  <% else -%>
  DocumentRoot <%= @params[:docroot] %>
  <%= @params[:deploy][:passenger_handler] -%>BaseURI /
  <% end -%>
  <%= @params[:deploy][:passenger_handler] -%>Env <%= @params[:rails_env] %>

  <Directory <%= @params[:docroot] %>>
    Options FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>

  <Directory ~ "\.svn">
    Order allow,deny
    Deny from all
  </Directory>

  <Directory ~ "\.git">
    Order allow,deny
    Deny from all
  </Directory>

  <LocationMatch "^/assets/.*$">
    Header unset ETag
    FileETag None
    # RFC says only cache for 1 year
    ExpiresActive On
    ExpiresDefault "access plus 1 year"
  </LocationMatch>

  LogLevel info
  ErrorLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-ssl-error.log
  CustomLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-ssl-access.log combined
  CustomLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-ssl-ganglia.log ganglia

  FileETag none

  RewriteEngine On
  Include <%= @params[:rewrite_config] %>-ssl*
  RewriteLog <%= node[:apache][:log_dir] %>/<%= @application_name %>-ssl-rewrite.log
  RewriteLogLevel 0

  # Canonical host
  #RewriteCond %{HTTP_HOST}   !^<%= @params[:server_name] %> [NC]
  #RewriteCond %{HTTP_HOST}   !^$
  #RewriteRule ^/(.*)$        http://<%= @params[:server_name] %>/$1 [L,R=301]

  RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|jpeg|png)$
  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
  RewriteRule ^.*$ /system/maintenance.html [L]

  Include <%= @params[:local_config] %>-ssl*
</VirtualHost>
<% end -%>

如果您有任何问题,请随时提出。

最佳

丹尼尔

修改

或者您只是复制了我快速开发的这本食谱 https://github.com/neonlex/massive-octo-computing-machine 。 但是OpsWorks将来默认支持这一点。

答案 1 :(得分:5)

我对OpsWorks和Chef知之甚少,但这就是我为了让它发挥作用所做的一切。

首先,我必须创建一个在setup事件期间运行的rails配方,以创建资产的符号链接目录。这是OpsWorks可以访问的公共仓库。

<强>食谱/轨道/食谱/ symlink_assets.rb:

node[:deploy].each do |application, deploy|
  Chef::Log.info("Ensuring shared/assets directory for #{application} app...")

  directory "#{deploy[:deploy_to]}/shared/assets" do
    group deploy[:group]
    owner deploy[:user]
    mode 0775
    action :create
    recursive true
  end
end

然后,在我的应用中,我必须创建 deploy / before_migrate.rb:

Chef::Log.info("Running deploy/before_migrate.rb...")

Chef::Log.info("Symlinking #{release_path}/public/assets to #{new_resource.deploy_to}/shared/assets")

link "#{release_path}/public/assets" do
  to "#{new_resource.deploy_to}/shared/assets"
end

rails_env = new_resource.environment["RAILS_ENV"]
Chef::Log.info("Precompiling assets for RAILS_ENV=#{rails_env}...")

execute "rake assets:precompile" do
  cwd release_path
  command "bundle exec rake assets:precompile"
  environment "RAILS_ENV" => rails_env
end

在部署过程中调用此函数并编译资产。

答案 2 :(得分:5)

请注意,如果您使用new OpsWorks feature将环境变量传递到Rails应用,则需要在rake调用中包含这些变量(因为它们不会永久来源部署用户的环境)。

我在deploy/before_migrate.rb中执行以下操作(基于this articlethis recipe):

Chef::Log.info("Precompiling assets for RAILS_ENV=" \
               "#{new_resource.environment['RAILS_ENV']}...")

execute 'rake assets:precompile' do
  cwd release_path
  command 'bundle exec rake assets:precompile'
  environment new_resource.environment
end

答案 3 :(得分:3)

在AWS Opsworks中,我使用以下方法:

execute 'rake assets:precompile' do
  cwd "#{node[:deploy_to]}/current"
  user 'root'
  command 'bundle exec rake assets:precompile'
  environment 'RAILS_ENV' => node[:environment_variables][:RAILS_ENV]
end

我以root身份运行此命令,因为该实例需要正确的权限才能写入release路径。以deploy用户身份运行命令会呈现权限被拒绝错误。