Search code examples
ruby-on-railsamazon-elb

Rails production not work in AWS load balancer


My Rails 6 App work fine with development mode in EC2 instances. But when config to use production mode. The load balancer not able to do health check and not able to run the app.

My health check:

enter image description here

Security: Load Balancer

enter image description here

enter image description here

Security: Rails App(s)

enter image description here

enter image description here

Load balancer worked in development

enter image description here

Here the development that work with load balancer

Start rails:

rails s -p 3000 -b 0.0.0.0

then responded

=> Booting Puma
=> Rails 6.0.3.2 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000

config/environments/development.rb

Rails.application.configure do
  config.hosts << "xxxxxxxx.us-east-2.elb.amazonaws.com" #This is public dns of load balance
  config.cache_classes = false
  config.eager_load = false
  config.consider_all_requests_local = true
  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = true
    config.action_controller.enable_fragment_cache_logging = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end
  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }

  config.action_mailer.perform_caching = false
  config.active_support.deprecation = :log
  config.assets.debug = true
  config.assets.quiet = true
  config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end

Below is production(that not working)

config/environments/production.rb

Start rails:

RAILS_ENV=production rails s -p 3000 -b 0.0.0.0

then responded:

=> Booting Puma
=> Rails 6.0.3.2 application starting in production 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: production
* Listening on tcp://0.0.0.0:3000


Rails.application.configure do
  config.hosts << "xxxxxxxx.us-east-2.elb.amazonaws.com" #This is public dns of load balance
  config.hosts << "3.14.65.84"
  config.cache_classes = true
  config.eager_load = true
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
  config.assets.compile = false
  config.log_level = :debug
  config.log_tags = [ :request_id ]
  config.action_mailer.perform_caching = false
  config.i18n.fallbacks = true
  config.active_support.deprecation = :notify
  config.log_formatter = ::Logger::Formatter.new
  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end
end

Load Balancer: Health Check not work!

enter image description here

I also tried:

  1. copy config/environments/development.rb to production.rb and then run as production environment the result =====> Health Check Not Work!
  2. copy config/environment/production.rb to development.rb and then run as development environment the result =====> Health Check Work!

It seems nothing about the rails config, but the way it handle production in AWS

Help: How to make this Rails 6 work as production in AWS EC2 with load balancer ?


Solution

  • Instead of ping to root path, I think better if you create your own routes for health check in application like this:

    # controller
    class HealthCheckController < ApplicationController
      def show
        render body: nil, status: 200
      end
    end
    
    # routes
    get '/health_check', to: 'health_check#show'
    

    then update ping path in LB health check to /health_check

    Edit:

    Add config.hosts.clear replaced config.hosts << "xxxxxxxx.us-east-2.elb.amazonaws.com" in production config file to make rails accept request