[RUBY] Procedure for publishing an application using AWS (5) Publish an application

Introduction

I will describe the procedure to publish the application using AWS. This article publishes the application.

Ready to clone application code to EC2 server

Change to the ".ssh" directory

Execute the following command and change to the ".ssh" directory.

cd ~/.ssh/

ssh connection

Execute the following command to access the EC2 instance with ssh. (When the downloaded pem file name is "xxx.pem" and the Elastic IP is 12.345.67.890)

ssh -i xxx.pem [email protected]

Register your SSH key on Github

In order to access Github from an EC2 instance, you need to register the SSH public key of the EC2 instance on Github. If you do not register the SSH key, a permission error will occur and you will not be able to clone. By registering the SSH key on Github, you will be authenticated and you will be able to clone the code.

Execute the following command to create an SSH key pair for the EC2 server.

ssh-keygen -t rsa -b 4096

Execute the following command to display the generated SSH public key and copy the value.

cat ~/.ssh/id_rsa.pub

When you access the following URL, the screen looks like the image. https://github.com/settings/keys

SSH鍵登録スクショ.png

Enter an arbitrary title in the "Title" field, paste the SSH public key you copied earlier in the "Key" field, and click "Add SSH key".

Execute the following command and check if SSH connection is possible.

ssh -T [email protected]

If Permission denied (public key). Is displayed, the SSH key setting is incorrect.

About options for the "ssh-keygen" command

The "ssh-keygen" command is a command to create a private key and a public key of the public key authentication method. "-T" is an option to specify the encryption format of the key to be created from "rsa", "dsa", "ecdsa", and "ed25519". "-B" is a command that specifies the number of bits of the key to be created. This means that the above command will generate a 4096-bit key in RSA encryption format.

Application server settings

An application server is software that operates an application in response to a request from a browser.

For example, when checking the operation of a Ruby on Rails application in a local environment, enter the command "rails s". This starts an application server called "puma". In this state, you can check the operation of the rails application by accessing "localhost: 3000" from the browser. (localhost: 3000 points to your PC)

Similarly, in order to run an application on the EC2 server, it is necessary to start the application server on the EC2 server.

Install Unicorn

Unicorn is one of the most popular application servers. Unicorn can be started with the "unicorn_rails" command instead of the "rails s" command.

Unicorn is written in Ruby and is gemized. Add the following description to the Gemfile. Unicorn is used only in the production environment, so it is not necessary in the development environment.

Gemfile


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

Execute the following command in the application directory.

bundle install

Create the following Unicorn configuration file directly under the config directory.

config/unicorn.rb


#Put the directory where the application code on the server is installed in a variable
app_path = File.expand_path('../../', __FILE__)

#Determine application server performance
worker_processes 1

#Specify the directory where the application is installed
working_directory app_path

#Specify the location of the files required to start Unicorn
pid "#{app_path}/tmp/pids/unicorn.pid"

#Specify the port number
listen 3000

#Specify a file to log errors
stderr_path "#{app_path}/log/unicorn.stderr.log"

#Specify the file to record the normal log
stdout_path "#{app_path}/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

What is a process?

A process is a run-time unit of all programs running on a PC (server). The program mentioned here includes a browser, music playback software, GUI such as Excel, and execution of a script language such as Ruby. There are as many processes as there are programs running.

What is a worker

Unicorn can disrupt the process. The split process is called a worker. By splitting the process, the response to the request can be speeded up. Set the number of workers in the item called worker_processes. When a request comes from a browser etc., Unicorn workers run the rails application. rails compares the content of the request with the routing and finally responds with the appropriate View or json. Unicorn receives the response and returns it to the browser. This series of flow takes about 0.1 to 0.5 seconds. If the application is such that requests are constantly made at a higher speed, the processing may not be able to keep up with one worker and it may take a long time to respond or the server may stop. You can speed up the response of your application by increasing the number of worker_processes.

Unicorn settings

Setting items Details
worker_processes Accept requests Determine the number of workers to generate responses
working_directory When Unicorn runs rails code, it specifies a directory to look for files that it actually references, such as routing.
pid Specify the location to generate the file with the process id when Unicorn starts.
listen Specify which port number to accept the request.

Comment out the description about Uglifier

There is a gem called Uglifier to reduce the weight of Javascript. If you are using template literal notation (`) in Javascript, comment it out because Uglifier does not support this and will cause an error during deployment.

Comment out the following description in config / environments / production.rb.

config/environments/production.rb


# config.assets.js_compressor = :uglifier

Reflect changes in remote repositories

Commit the file and push it to Github. If you have a branch, merge it into the master branch.

Clone code from Github

Clone the Unicorn-configured code to your EC2 instance.

Create a / var / www directory

After SSH connection to the EC2 instance, execute the following command to create the / var / www directory.

sudo mkdir /var/www/

Change permissions to ec2-user

Execute the following command to change the permissions of the created www directory to ec2-user.

sudo chown ec2-user /var/www/

Get the repository URL from Github

Go to the application page on Github and copy the repository URL referring to the image below.

リポジトリURLスクショ.png

Clone code

Execute the following command to clone the code. (In the example below, when the user name of Github is "test1234" and the repository name is "testapp")

cd /var/www/
git clone https://github.com/test1234/testapp.git(The repository URL you copied earlier)

Production environment settings

Make settings to publish the service.

Expand EC2 capabilities

The current EC2 instance does not have enough memory, and an error may occur when installing a gem. Therefore, first increase the memory.

Prepare Swap area

When a computer performs processing, the processing contents are temporarily recorded in a place called memory. The capacity of memory is fixed, and if it exceeds that capacity, processing will stop with an error. Swap area is a file prepared to temporarily increase the memory capacity when the memory is about to be used up. Since EC2 does not have a Swap area by default, preparing it will prevent an error of insufficient memory.

Ssh connect to your EC2 instance and change to your home directory.

cd

Execute the following commands in order to secure the Swap area.

sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
sudo chmod 600 /swapfile1
sudo mkswap /swapfile1
sudo swapon /swapfile1
sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

install gem

Install the gems needed to launch the cloned application.

Execute the following command to change to the directory of the cloned application.

cd /var/www/testapp

Execute the following command to check if the version of Ruby installed by rbenv is used.

ruby -v

Install bundler to manage gems in production

Execute the following command in the local environment to check the version of bundler used in the development environment.

bundler -v

The version differs depending on the development environment, but this time it was 2.0.1. In order to install the same version in the production environment, SSH to the EC2 instance again and execute the following command.

gem install bundler -v 2.0.1(Same version as local environment)
bundle install

Set environment variables

Information that cannot be uploaded to Github for security reasons, such as database passwords, is set using environment variables. In rails, the value of an environment variable can be used by writing "ENV ['']".

Create secret_key_base

secret_key_base is a character string used to encrypt cookies. You need to prepare it when you run the rails application. Since it is a value that should not be leaked to the outside, refer to it from the environment variable.

Execute the following command to create secret_key_base. When you execute the command, a long character string will be generated, so copy it.

rake secret

Set environment variables on your EC2 instance

Environment variables are applied to the entire server by saving them in a file called / etc / environment. Use the vim command to write environment variables.

Execute the following command to edit / etc / enrvironment.

sudo vim /etc/environment

Edit / etc / environment as follows.

/etc/environment


DATABASE_PASSWORD='<MySQL root user password>'
SECRET_KEY_BASE='<The secret you copied earlier_key_base>'

After editing and saving, execute the following command and log out once.

exit

SSH into your EC2 instance again. Execute the following command and check if the environment variables are applied.

env | grep DATABASE_PASSWORD
env | grep SECRET_KEY_BASE

Release the port

EC2 instances that have just been launched can be accessed via SSH, but cannot be connected at all using other communication methods such as HTTP. Therefore, the EC2 instance used as a WEB server needs to open the port in advance so that HTTP can be connected.

In order to set the port, it is necessary to change the setting called security group of EC2. A security group is like a group to which an EC2 server belongs, and is for making network settings for multiple EC2 instances at once.

Log in to AWS, select the target instance from the EC2 instance list screen, and click the security group link. 18_セキュリティグループリンクスクショ.png

The screen will change to the security group setting screen, so click Edit on the Inbound tab. 19_インバウンド編集スクショ.png

When the Edit Inbound Rule pop-up screen appears, click Add Rule, type "Custom TCP Rule", protocol "TCP", port range "3000", source "Custom", "0.0. Set to "0.0/0". セキュリティグループポートスクショ.png

Launch rails in production

Before starting rails in the production environment, the MySQL settings in the development environment and the production environment are different at present, so adjust the MySQL settings in the development environment to the production environment.

Edit config / database.yml of the development environment as follows, commit, and push it to Github.

config/database.yml


production:
  <<: *default
  database: ~~~(Do not edit this as it depends on each application name)
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

Ssh connect to the EC2 instance and execute the following command.

git pull origin master

Execute the following command and change to the application directory.

cd /var/www/testapp

Execute the following command to create the database.

rails db:create RAILS_ENV=production

Execute the following command to execute the migration.

rails db:migrate RAILS_ENV=production

If the error Mysql2 :: Error: Can't connect to local MySQL server through socket occurs here, it is possible that MySQL has not started, so execute the following command to start MySQL. ..

sudo service mysqld start

Execute the following command to start unicorn in the production environment. "-C config / unicorn.rb" means to specify the configuration file, and "-E production" means to operate in the production environment. "-D" is an abbreviation for Daemon, which is a command that allows you to type another command in the terminal while starting a program.

bundle exec unicorn_rails -c config/unicorn.rb -E production -D

Now, try accessing http://123.456.789:3000/ with your browser. (When Elastic IP is 123.456.789) Success if a screen that does not reflect css is displayed.

Compile the asset file

The development environment has a mechanism to automatically compile asset files (image, css, javascript) for each access, but in the production environment it is not executed for each access due to performance. Therefore, it is necessary to compile the assets in advance in the production environment. Execute the following command to compile the asset.

rails assets:precompile RAILS_ENV=production

If the compilation is successful, restart rails to check the reflection. First, check the Unicorn process from the terminal and kill the process.

Execute the following command to check the Unicorn command. The ps command is a command to check the currently running process, and aux is an option to make the display result of the ps command easier to see. | By using grep unicorn, only unicorn related processes are extracted from the result of the ps command.

ps aux | grep unicorn

Check the PID of unicorn_rails master from the display result. Here, it is assumed that it is "17877" as an example.

Execute the following command to stop the Unicorn process.

kill 17877

Execute the following command to start Unicorn again. At this time, add RAILS_SERVE_STATIC_FILES = 1 at the beginning. This will allow Unicorn to find the compiled asset.

RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

Try accessing http://12.345.67.890:3000/ again with your browser. (When Elastic IP is 12.345.67.890) This time the screen should be displayed with css reflected.

Check when rails doesn't start properly

--Forgot to push, forget to pull EC2 server --Check /var/www/testapp/log/unicorn.stderr.log on the EC2 server side to see if there are any errors. --Is MySQL started correctly? --Is SECRET_KEY_BASE etc. set correctly? --Try restarting the EC2 instance

reference

ssh-keygen command Template literal notation

Related article

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 (6) Install Nginx] (https://qiita.com/osawa4017/items/9b707baf6ddde623068c)

Recommended Posts

Procedure for publishing an application using AWS (5) Publish an application
Procedure for publishing an application using AWS (6) Introduce Nginx
Procedure for publishing an application using AWS (4) Creating a database
How to publish an application using AWS (3) EC2 instance environment construction
Procedure for building an authorization server using Authlete (CIBA compatible version)
How to publish an application on Heroku
AdMob setting procedure for Android application (December 2016)
Send an email using JavaMail on AWS
A memorandum for creating an extended logger using org.slf4j.Logger
Procedure for publishing an application using AWS (4) Creating a database
Building an environment for creating apps with Rails and Vue
Procedure for loading JDBC of MySQL using JAVA-Eclipse
Environment construction procedure for using PowerMock with JUnit
[For beginners] Procedure for creating a controller using rails
I tried using the Migration Toolkit for Application Binaries
I tried using an extended for statement in Java
A memorandum for creating an extended logger using org.slf4j.Logger