How to precompile assets with Chef?

后端 未结 4 1902
慢半拍i
慢半拍i 2021-02-02 00:27

OpsWorks isn\'t precompiling assets on deploy. I found this recipe in this thread but I think it\'s not complete though, or missing something because I get an error about

相关标签:
4条回答
  • 2021-02-02 00:43

    Before OpsWorks supports the Asset Pipeline out of the box, you could do this. Create a file deploy/before_symlink.rb with the following content in your rails application.

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

    If you deploy your Rails application to a different environment, change the RAILS_ENV.

    If you use a NGINX/Unicorn stack, you have to modify the /assets resource. Just copy the following content in a file named unicorn/templates/default/nginx_unicorn_web_app.erb in your cookbooks.

    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 %>
    

    If you use a Apache2/Passenger stack, you have to modify the /assets resource. Just copy the following content in a file named passenger_apache2/templates/default/web_app.conf.erb in your cookbooks.

    <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 -%>
    

    If you have questions feel free to ask.

    Best Daniel

    EDIT:

    Or you just copy over this cookbooks https://github.com/neonlex/massive-octo-computing-machine I developed quickly. But OpsWorks should support this by default in the future.

    0 讨论(0)
  • 2021-02-02 00:51

    Note that if you're passing environment variables to your Rails app using the new OpsWorks feature, you'll need to include these variables in your rake invocation (as they don't get permanently sourced into the deploy user's environment).

    I do the following (based on this article and this recipe) in deploy/before_migrate.rb:

    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
    
    0 讨论(0)
  • 2021-02-02 01:04

    I know very little about OpsWorks and Chef, but here's what I did to get it working.

    First, I had to create a rails recipe that runs during the setup event to create the symlink directory for the assets. This sits in a public repo that OpsWorks can access.

    cookbooks/rails/recipes/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
    

    Then, in my app, I had to create 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
    

    This get called during the deployment process and compiles the assets.

    0 讨论(0)
  • 2021-02-02 01:04

    In AWS Opsworks I use the following recipe:

    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
    

    I run this command as root because the instance needs the right permission to write to the release path. Running the command as the deploy user renders a permission denied error.

    0 讨论(0)
提交回复
热议问题