I will describe the procedure to publish the application using AWS. This article uses Capistrano to automate the deployment process.
Capistrano is written in Ruby and Gem is open to the public. This article describes the procedure for introducing Capistrano to rails, but it seems that it can be used with other frameworks such as PHP.
Edit the Gemfile as follows.
Gemfile
group :development, :test do
gem 'capistrano'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano3-unicorn'
end
Execute the following command in the terminal to read the Gemfile.
bundle install
Execute the following command to generate Capistrano related files.
bundle exec cap install
The following files are generated. Details of each file will be described later.
Some libraries (Gems) need to be loaded for Capistrano to work. Capfile is a file for specifying which of the Capistrano-related libraries to load.
Edit the Capfile as follows. This will read the directory containing the file that describes the behavior required for deployment. Reference
Capfile
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
Production.rb and staging.rb are created in the config / deploy directory. These files are files that describe the settings for deployment. production.rb is the production environment configuration file, and staging.rb is the staging environment configuration file. Describe the following contents in production.rb (staging.rb).
--Server host name --AWS server login username --Server role --Ssh settings --Other settings associated with the server
Modify production.rb as follows. (When the application's Elastic IP is 12.345.67.890)
config/deploy/production.rb
server '12.345.67.890', user: 'ec2-user', roles: %w{app db web}
In deploy.rb created in the config directory, describe the settings common to the production environment and staging environment. Specifically, the following is described.
--Application name --git repository --SCM (Software Configuration Management) to be used --Task --Commands to be executed in each task
Delete the description of deploy.rb and change it as follows. (Here, as an example, Capistrano version is "3.11.0", application name is "testapp", Github user name is "test1234", repository name is "testapp", ruby version is "2.5.1", local PC The path to the SSH key (pem) of the EC2 instance in is "~ / .ssh / xxx.pem".)
config/deploy.rb
# config valid only for current version of Capistrano
#Described the version of capistrano. Continue to use the fixed version and prevent troubles due to version change
lock '3.11.0'
#Used to display Capistrano logs
set :application, 'testapp'
#Specify from which repository the app should be pulled
set :repo_url, '[email protected]:test1234/testapp.git'
#Specify a directory to be referenced in common even if the version changes
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :rbenv_type, :user
set :rbenv_ruby, '2.5.1'
#Which public key to use for deployment
set :ssh_options, auth_methods: ['publickey'],
keys: ['~/.ssh/xxx.pem']
#Location of the file containing the process number
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
#Location of Unicorn configuration files
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5
#Description for restarting Unicorn after the deployment process is finished
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
task :restart do
invoke 'unicorn:restart'
end
end
It is described in a file called gemfile.lock.
A DSL is a program that is prepared in a pseudo manner in order to improve the efficiency of a specific process. For example, there is a description of set: name,'value'. At this time,'value' can be fetched by setting fetch name. The set value can also be retrieved from deploy.rb and production.rb. Also, there is a description of task: xx do ~ end. This adds a task in addition to the one required by Capfile. What is described here is executed at the time of cap deploy.
When the automatic deployment by Capistrano is executed, the directory structure of the production environment changes. Multiple directories are created, such as Capistrano backing up applications. For example, the following directory is created.
--releases directory --Applications deployed through Capistrano are grouped in a directory called releases. Since the past application remains here, it is possible to revert to the previous version if something goes wrong during deployment. The description of set: keep_releases in deploy.rb specifies the number to be saved, and this time it is set to save the version for 5 times. --current directory --The latest in the releases directory is automatically copied to this directory. In other words, the contents of the application in this directory are the contents of the currently deployed application. --shared directory --The directories that are commonly referenced are stored even if the version changes. Specifically, log, public, tmp, vendor directories are stored.
With the introduction of Capistrano, the directory structure of the production environment will change, so the description of unicorn.rb will also change accordingly.
Modify unicorn.rb as follows.
config/unicorn.rb
#Put the directory where the application code on the server is installed in a variable
#Change: Make the hierarchy one deeper
app_path = File.expand_path('../../../', __FILE__)
#Determine application server performance
worker_processes 1
#Specify the directory where the application is installed
#Change: specify current
working_directory "#{app_path}/current"
#Specify the location of the files required to start Unicorn
#Changed: Added shared directory
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
#Specify the port number
#Changed: Added shared directory
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
#Specify a file to log errors
#Changed: Added shared directory
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
#Specify the file to record the normal log
#Changed: Added shared directory
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
#Set maximum time to wait for Rails application response
timeout 60
preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true
check_client_connection false
run_once = true
before_fork do |server, worker|
defined?(ActiveRecord::Base) &&
ActiveRecord::Base.connection.disconnect!
if run_once
run_once = false # prevent from firing again
end
old_pid = "#{server.config[:pid]}.oldbin"
if File.exist?(old_pid) && server.pid != old_pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH => e
logger.error e
end
end
end
after_fork do |_server, _worker|
defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
Since the directory structure has changed, change rails.conf as follows. (The case where the application name is "testapp" and the Elastic IP is "12.345.67.890" is described as an example)
rails.conf
upstream app_server {
#Changed to refer to in shared
server unix:/var/www/testapp/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name 12.345.67.890;
#Set the maximum size of files uploaded from the client to 2 giga. The default is 1 mega, so keep it large
client_max_body_size 2g;
#Changed to refer to in current
root /var/www/testapp/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
#Changed to refer to in current
root /var/www/testapp/current/public;
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
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;
}
error_page 500 502 503 504 /500.html;
}
After changing the Nginx settings, SSH into the EC2 instance and Execute the following command to reload and restart.
sudo service nginx reload
sudo service nginx restart
Since it can not be deployed unless MySQL is started, Execute the following command and restart MySQL just in case.
sudo service mysqld restart
Kill the unicorn master process before performing the automatic deployment. First, execute the following command to check the process ID of unicorn master.
ps aux | grep unicorn
Kill the process confirmed by the following command. (This time, the process ID of unicorn master is 17877)
kill 17877
Push all the files edited this time to the master branch.
Execute the following command in the local environment to perform automatic deployment. Success if there are no errors.
bundle exec cap production deploy
--Run again --Are there any mistakes in the description? --Are you skipping the procedure?
You can access the application by entering the Elastic IP in the URL field of your browser (no need to add: 3000).
--Are there any errors in the development environment? --Are there any errors in /var/www/testapp/current/log/unicorn.stderr.log (if the repository name is "testapp") -Did you forget to push or pull? --Try restarting MySQL or Nginx --Try restarting the EC2 instance
Procedure to publish application using AWS (1) Create AWS account Procedure to publish application using AWS (2) Create EC2 instance [How to publish an application using AWS (3) EC2 instance environment construction] (https://qiita.com/osawa4017/items/8dc09203f84e04bf0e66) [Procedure to publish application using AWS (4) Create database] (https://qiita.com/osawa4017/items/7dba25f4fa30ab0b1246) [Procedure to publish application using AWS (5) Publish application] (https://qiita.com/osawa4017/items/6f3125fcc21f73024311) [Procedure to publish application using AWS (6) Install Nginx] (https://qiita.com/osawa4017/items/9b707baf6ddde623068c)
Recommended Posts