[RUBY] Déploiement facile avec Capistrano + AWS (EC2) + Rails

introduction

J'ai utilisé Capistrano pour déployer ma propre application Rails.

En gros, j'ai fait référence à l'article suivant. (Édition Capistrano) Le commentaire AWS le plus poli au monde. Jusqu'à ce que vous apportiez l'application Rails à AWS à l'aide d'EC2

Dans cet article, j'ai résumé les parties remplies d'erreurs avec l'article de référence, j'espère donc que vous le trouverez utile.

Fichier à créer

Côté local

Côté serveur (EC2)

Code source

Gemfile Liste des gemmes à installer.

(local)Gemfile


group :development, :test do
 gem 'capistrano'
 gem 'capistrano-bundler'
 gem 'capistrano-rails'
 gem 'capistrano-rbenv'
end

group :production, :staging do
  gem 'unicorn'
end

D'autres documents peuvent utiliser le gem'capistrano3-unicorn ', mais il n'est pas utilisé ici pour les paramètres détaillés.

Capfile

Il s'agit du fichier de paramétrage pour l'ensemble du capistrano.

(local)Capfile


require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
#Configuré pour lire le fichier qui décrit la tâche. Spécifiez l'emplacement et l'extension.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Dans l'article de référence, la dernière ligne est "~ / *. Rb", mais dans la version actuelle, rake est la valeur par défaut, alors utilisez-la.

Notez que le format de fichier lib / capistrano / tasks / unicorn.rake que vous créerez plus tard est **. Rake **. Faisons du format de fichier défini le même format de fichier. (Je suis un peu coincé ici.)

config/deploy/production.rb

Il s'agit d'un fichier qui décrit les paramètres de l'environnement de production.

(local)config/deploy/production.rb


#Décrivez l'adresse IP du serveur EC2, le nom d'utilisateur pour vous connecter au serveur EC2 et le rôle du serveur.
server '**.***.***.***', user: 'yuki', roles: %w[app db web]

#Décrivez les informations clés pour la connexion SSH au serveur à déployer
set :ssh_options, keys: '~/.ssh/app_key_rsa'

config/deploy.rb

Décrivez les paramètres qui s'appliquent à la fois à l'environnement de production et à l'environnement de stading.

(local)config/deploy.rb


#Version fixe de capistrano
lock '3.14.1'

#Nom de l'application à déployer
set :application, 'golfour'

#dépôt git à cloner
set :repo_url, '[email protected]:app/app_aws.git'

#La branche à déployer. Il n'est pas nécessaire que la valeur par défaut soit master.
set :branch, 'master'

#Le répertoire dans lequel effectuer le déploiement.
set :deploy_to, '/var/www/rails/app'

# secret_base_Ajouté pour lire la clé
set :linked_files, %w[config/master.key]

#Un fichier avec un lien symbolique.
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/settings.yml', '.env')

#Un dossier avec des liens symboliques.
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')

#Le nombre de versions à conserver. Enregistrez jusqu'à 5 historiques.
set :keep_releases, 5

#version rubis
set :rbenv_ruby, '2.5.1'

#Le niveau du journal à sortir.
set :log_level, :debug

namespace :deploy do
  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart'
  end

  desc 'Create database'
  task :db_create do
    on roles(:db) do |_host|
      with rails_env: fetch(:rails_env) do
        within current_path do
          execute :bundle, :exec, :rake, 'db:create'
        end
      end
    end
  end

  desc 'Run seed'
  task :seed do
    on roles(:app) do
      with rails_env: fetch(:rails_env) do
        within current_path do
          execute :bundle, :exec, :rake, 'db:seed'
        end
      end
    end
  end

  after :publishing, :restart

  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
    end
  end
end

Les deux codes suivants sont ajoutés en plus de l'article de référence.

Ici, vers des liens symboliques (fichiers que vous ne souhaitez pas ouvrir, comme la configuration dans gitignore)

# secret_base_Ajouté pour lire la clé
set :linked_files, %w[config/master.key]

#Un fichier avec un lien symbolique.
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/settings.yml', '.env')

lib/capistrano/tasks/unicorn.rake

Un fichier qui décrit la tâche de configuration de la licorne.

(local)lib/capistrano/tasks/unicorn.rake


#Spécifiez le fichier pid de la licorne et le répertoire du fichier de configuration
namespace :unicorn do
  task :environment do
    set :unicorn_pid,    "#{current_path}/tmp/pids/unicorn.pid"
    set :unicorn_config, "#{current_path}/config/unicorn/production.rb"
  end

  #Méthode pour démarrer la licorne
  def start_unicorn
    within current_path do
      execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
    end
  end

  #Méthode pour arrêter la licorne
  def stop_unicorn
    execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
  end

  #Méthode pour redémarrer la licorne
  def reload_unicorn
    execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})"
  end

  #Méthode pour tuer unicron
  def force_stop_unicorn
    execute :kill, "$(< #{fetch(:unicorn_pid)})"
  end

  #tâche pour démarrer la licorne
  desc 'Start unicorn server'
  task start: :environment do
    on roles(:app) do
      start_unicorn
    end
  end

  #tâche d'arrêter la licorne
  desc 'Stop unicorn server gracefully'
  task stop: :environment do
    on roles(:app) do
      stop_unicorn
    end
  end

  #Si la licorne est déjà en cours d'exécution, redémarrez-la, sinon, démarrez la tâche
  desc 'Restart unicorn server gracefully'
  task restart: :environment do
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        reload_unicorn
      else
        start_unicorn
      end
    end
  end

  #tâche de tuer la licorne
  desc 'Stop unicorn server immediately'
  task force_stop: :environment do
    on roles(:app) do
      force_stop_unicorn
    end
  end
end

Comme je l'ai expliqué dans Capfile, veuillez noter qu'il s'agit d'unicorn.rake. S'il est défini dans .rb dans Capfile, ce sera unicorn.rb.

config/unicorn/production.rb Ceci est le fichier de configuration de la licorne.

(local)config/unicorn/production.rb



#Nombre de travailleurs. Voir ci-dessous
$worker = 2
#Décidez du nombre de secondes écoulées avant de supprimer le travailleur
$timeout = 30
#Notez que le nom de votre application, actuel, est joint.
$app_dir = '/var/www//rails/golfour/current'
#Spécifiez le numéro de port pour recevoir la demande. Voir ci-dessous
$listen = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
#Répertoire des fichiers de gestion PID
$pid = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
#Répertoire des fichiers qui crachent les journaux d'erreurs
$std_log = File.expand_path 'log/unicorn.log', $app_dir

#Défini de sorte que ce qui est défini ci-dessus soit appliqué
worker_processes  $worker
working_directory $app_dir
stderr_path $std_log
stdout_path $std_log
timeout $timeout
listen  $listen
pid $pid

#Définir s'il faut déployer à chaud
preload_app true

#Définissez ce qu'il faut faire avant la fourchette. Voir ci-dessous
before_fork do |server, _worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
  old_pid = "#{server.config[:pid]}.oldbin"
  if old_pid != server.pid
    begin
      Process.kill 'QUIT', File.read(old_pid).to_i
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

#Définissez quoi faire après la fourchette. Voir ci-dessous
after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

shared/config/settings.yml

(server)shared/config/settings.yml


production:
  secret_key_base: jr934ugr89vwredvu9iqfj394vj9edfjcvnxii90wefjc9weiodjsc9o i09fiodjvcijdsjcwejdsciojdsxcjdkkdsv 
(#Collez le nombre aléatoire généré)

shared/config/database.yml

(server)shared/config/database.yml



default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: golfour_development
  username: yuki
  password: password
  host: db
  socket: /tmp/mysql.sock

test:
  <<: *default
  database: golfour_test
  username: yuki
  password: password
  host: db-test
  socket: /tmp/mysql.sock

production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  host: <%= ENV['DB_HOSTNAME'] %>

shared/.env

Décrivez ici les variables d'environnement utilisées dans datacbase.yml.

(server)shared/.env


DB_NAME=*****
DB_USERNAME=*****
DB_PASSWORD=*****
DB_HOSTNAME=*****

/etc/nginx/conf.d/app.conf

conf:(server)/etc/nginx/conf.d/app.conf


#Paramètres de répertoire pour divers journaux
  error_log  /var/www/rails/mumu/current/log/nginx.error.log;
  access_log /var/www/rails/mumu/current/log/nginx.access.log;
#Capacité maximale pour recevoir le traitement
  client_max_body_size 2G;
  upstream app_server {
#Chemin de socket Licorne avec lequel travailler
    server unix:/var/www/rails/mumu/current/tmp/sockets/.unicorn.sock fail_timeout=0;
  }
  server {
    listen 80;
    server_name 127.0.0.1; #Changez pour votre propre adresse IP!
#Temps d'attente pour la prochaine requête (secondes)
    keepalive_timeout 5;
#Répertoire pour lire les fichiers statiques
    root /var/www/rails/mumu/current/public;
#Répertoire du cache
    try_files $uri/index.html $uri.html $uri @app;
    location @app {
      # HTTP headers
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app_server;
    }
#Où placer la page d'erreur
    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /var/www/rails/mumu/current/public;
    }
  }

Déployer la commande

bundle exec cap production deploy

Liste des erreurs

Mémoire insuffisante

Se produit après l'exécution d'un déploiement. Cela était dû à une mémoire insuffisante de EC2.

console


virtual memory exhausted

Solution: créez un fichier d'échange

Il s'agit d'une méthode d'amplification de la mémoire afin qu'elle puisse être utilisée en déplaçant temporairement la mémoire inutilisée vers un autre emplacement. Si vous vous référez à l'article suivant, vous pouvez facilement l'implémenter, alors faites-le.

référence: Qu'est-ce qu'un fichier d'échange [Rails] Déployer sur EC2 avec Capistrano: dépanner EC2 à court de mémoire virtuelle

Missing secret_key_base for 'production' environment

Il s'agit également d'une erreur survenue lors de l'exécution du déploiement.

La cause était que le fichier master.key était manquant. Le secret_key_base est répertorié dans le fichier credentials.yml.enc en premier lieu. Cependant, ce fichier était chiffré et j'avais besoin de master.key pour le lire, mais j'obtenais une erreur car je ne l'avais pas.

Solution

・ Créer shared / master.key -Ajout de master.key au lien symbolique

Ce faisant, l'erreur a disparu.

Référence: Le déploiement automatique avec Capistrano donne une erreur de "Missing secret_key_base for'production'environment"

Recommended Posts

Déploiement facile avec Capistrano + AWS (EC2) + Rails
J'ai essayé le déploiement automatique avec CircleCI + Capistrano + AWS (EC2) + Rails
[Rails] Nginx, déploiement de l'environnement Puma et étude du serveur [AWS EC2]
Lancer des rails sur EC2 (déploiement manuel)
rails Le déploiement AWS n'est pas reflété
[EC2 / Vue / Rails] Procédure de déploiement EC2 pour Vue + Rails
[Rails] Construction de l'environnement d'instance AWS EC2
[Rails] Récapitulatif des incidents liés aux erreurs de déploiement AWS
Utilisation de Java avec AWS Lambda-Implementation-Stop / Launch EC2
[Rails] Publication d'images par CarrierWave [AWS EC2]
[AWS] Publier l'application Rails avec nginx + puma
Déployer des rails sur ECS Fargate avec AWS Copilot
Recette pour déployer des applications Rails sur AWS EC2
Créer un site EC avec Rails5 ⑤ ~ Modèle client ~
Créer un site EC avec Rails 5 ⑩ ~ Créer une fonction de commande ~
Facile à afficher Hello World avec Rails + Docker
Créer un site EC avec Rails 5 ⑨ ~ Créer une fonction de panier ~
Créer un site EC avec Rails5 ④ ~ En-tête et pied de page ~
Créez un site EC avec Rails5 ⑥ ~ entrée de données de départ ~
Lancez EC2 Rails
[Rails 6] Erreur d'exécution avec $ rails s
Procédure de déploiement de Rails Heroku
Manipuler le dispositif avec des rails
[Rails] Didacticiel Apprendre avec les rails
Déployer RAILS sur EC2
[Rails] Flux de déploiement Heroku
[Rails] Test avec RSpec
[Rails] Développement avec MySQL
Prend en charge la multilinguisme avec Rails!
Création du premier LINEbot avec AWS Cloud9 (déploiement Rails + Heroku)
Que faire si une erreur d'authentification de clé SSH se produit lors du déploiement automatique sur EC2 avec Capistrano