2015年10月29日木曜日

AWS無料利用枠のインスタンスで、Ruby on Railsの環境を作成してみる②

こんにちは、井下です。

前回はAWS無料利用枠のインスタンスを使って、とりあえずRailsがコンソール起動できるところまでの環境を構築しました。

今回はデフォルトで入ってるツール・ソフトウェア群を、よりスペックの良いものに差し替える工程を説明していきます。
なお、差し替え対象は下記の3つです。
  • JavaScriptランタイム
  • データベース
  • アプリケーションサーバ・Webサーバ
今回はJavaScriptランタイムと、データベースの差し替えを行います。
アプリケーションサーバおよびWebサーバは、次回差し替えを行っていきます。

1.JavaScriptランタイムの差し替え

前回も触れましたが、気軽に利用できるJavaScriptランタイムとして、「therubyracer」がありますが、bundle installに失敗するケースが出てきたり、メモリ消費量が多めな問題があります。

そこでよく利用されるJavaScriptランタイムの、「node.js」を導入してみます。

まずはGit Hubに掲載されているnode.jsのインストール手順に従って、node.jsをインストールしてみます。

[ec2-user@ip-xxx ~]$ curl --silent --location https://rpm.nodesource.com/setup | bash -

## Inspecting system...

+ rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release
+ uname -m

## Confirming "el7-x86_64" is supported...

+ curl -sLf -o /dev/null 'https://rpm.nodesource.com/pub/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'

## Downloading release setup RPM...

+ mktemp
+ curl -sL -o '/tmp/tmp.s0QxNR3NXV' 'https://rpm.nodesource.com/pub/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'

## Installing release setup RPM...

+ rpm -i --nosignature --force '/tmp/tmp.s0QxNR3NXV'
error: can't create transaction lock on /var/lib/rpm/.rpm.lock (No such file or directory)

Error executing command, exiting

…が、ダメでした。権限の問題らしいので、sudoしてみても結果は変わらず。
仕方がないので、ソースを入手してインストールする方法を試してみたところ、こちらはインストールができました。

まずは、最新(2015年10月時点)のバージョン、0.12.7のソースコードを入手します。
[ec2-user@ip-xxx ~]$ mkdir work
[ec2-user@ip-xxx ~]$ cd work/
[ec2-user@ip-xxx work]$ wget http://nodejs.org/dist/v0.12.7/node-v0.12.7.tar.gz
-bash: wget: command not found

…その前に、wgetがインストールされていなかったので、yumを使ってインストールします。

[ec2-user@ip-xxx work]$ sudo yum install wget
~略~
Complete!

今度こそ、0.12.7のソースコードを入手します。
[ec2-user@ip-xxx work]$ wget http://nodejs.org/dist/v0.12.7/node-v0.12.7.tar.gz
--2015-10-25 21:00:46--  http://nodejs.org/dist/v0.12.7/node-v0.12.7.tar.gz
Resolving nodejs.org (nodejs.org)... 104.20.23.46, 104.20.22.46, 2400:cb00:2048:1::6814:162e, ...
Connecting to nodejs.org (nodejs.org)|104.20.23.46|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 20063992 (19M) [application/gzip]
Saving to: ‘node-v0.12.7.tar.gz’

100%[=====================================================================================>] 20,063,992  7.49MB/s   in 2.6s

2015-10-25 21:00:49 (7.49 MB/s) - ‘node-v0.12.7.tar.gz’ saved [20063992/20063992]
[ec2-user@ip-xxx work]$ ls
node-v0.12.7.tar.gz

lsコマンドでソースコードを確認できたので、解凍した後、お決まりの「./configure」⇒「make」⇒「make install」でインストールします。

[ec2-user@ip-xxx work]$ tar xvf node-v0.12.7.tar.gz
[ec2-user@ip-xxx work]$ ls
node-v0.12.7  node-v0.12.7.tar.gz
[ec2-user@ip-xxx work]$ cd node-v0.12.7
[ec2-user@ip-xxx node-v0.12.7]$ ./configure
creating  ./icu_config.gypi
~略~
creating  ./config.gypi
creating  ./config.mk


[ec2-user@ip-xxx node-v0.12.7]$ make
~略~
[ec2-user@ip-xxx node-v0.12.7]$ sudo make install
~略~
[ec2-user@ip-xxx node-v0.12.7]$ node -v
v0.12.7

バージョン確認コマンドによって、node.jsがインストールできたことが確認できました。
これでtherubyracerは不要になったので、アンインストールしてしまいます。

[ec2-user@ip-xxx node-v0.12.7]$ cd ~/sample
[ec2-user@ip-xxx sample]$ gem list therubyracer

*** LOCAL GEMS ***

therubyracer (0.12.2)
[ec2-user@ip-xxx sample]$ gem uninstall therubyracer
[ec2-user@ip-xxx sample]$ gem list therubyracer

*** LOCAL GEMS ***

therubyracerがアンインストールされたので、Railsをコンソール起動して、JavaScriptランタイムが見つからないエラーが発生しないことを確認します。

[ec2-user@ip-xxx sample]$ rails c
Loading development environment (Rails 4.2.4)
irb(main):001:0>exit
[ec2-user@ip-xxx sample]$

特に問題はなさそうです。最後にGemfileを編集して、therubyracerを再度コメントアウトの状態にし、bundle installした際にインストールされないようにします。

[ec2-user@ip-xxx sample]$ vi Gemfile

「Gemgile」(緑字の部分を追記)

~略~
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
~略~

これでJavaScriptランタイムの差し替えが完了しました!



2.データベースの差し替え

Railsはデータベースと密接な関係にあり、一部の機能はデータベースによって使えないこともあります。
デフォルトではSQLiteを利用するように設定されており、特に設定ファイルを編集しなくても、すぐに利用できるようになっています。
ただ、SQLiteは大規模なデータの取り扱いには不向きのため、用途によっては差し替える必要性が出てきます。

今回は、PostgreSQLを導入し、Railsのデータベースとして設定してみます。

なお、前提として、Railsではデータベースの設定は(アプリケーションのルートディレクトリ)/confing/database.ymlに記載されています。
データベースの種類によって、database.ymlの設定項目が変化しますが、以前作った「sample」アプリケーションはSQLite用の設定項目になっています。
database.ymlを書き直してもいいのですが、Railsでアプリケーションの生成時にデータベースを指定すれば、そのデータベース用のdatabase.ymlを自動生成してくれるので、「データベースをPostgreSQLに指定した適当なアプリケーション作成」⇒「database.ymlをコピー」でdatabase.ymlをPostgreSQL用の設定項目にしてみます。

まずはデータベースをPostgreSQLに指定して、アプリケーションを作成します。

[ec2-user@ip-xxx sample]$ cd ~
[ec2-user@ip-xxx ~]$ rails new postgresql -d postgresql
~略~
extconf failed, exit code 1

Gem files will remain installed in /home/ec2-user/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/pg-0.18.3 for inspection.
Results logged to /home/ec2-user/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/extensions/x86_64-linux/2.2.0-static/pg-0.18.3/gem_make.out
An error occurred while installing pg (0.18.3), and Bundler cannot continue.
Make sure that `gem install pg -v '0.18.3'` succeeds before bundling.
         run  bundle exec spring binstub --all
~略~

いきなりエラーが発生しました。エラーメッセージによると、gemでPostgreSQL用のアクセスモジュールをインストールするように言われている(黄字の部分)ので、メッセージ通りのコマンドを実行します。

[ec2-user@ip-xxx ~]$ gem install pg -v '0.18.3'
Building native extensions.  This could take a while...
ERROR:  Error installing pg:
        ERROR: Failed to build gem native extension.

    /home/ec2-user/.rbenv/versions/2.2.3/bin/ruby -r ./siteconf20151026-2664-8owa57.rb extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.
~略~

またしてもダメでした。"libpq-fe.h"ファイルが見つからないと言われていますが、yumで"postgresql-devel"をインストールすることで解決しました。

[ec2-user@ip-xxx ~]$ sudo yum install postgresql-devel
~略~
Installed:
  postgresql-devel.x86_64 0:9.2.13-1.el7_1

Dependency Installed:
  postgresql.x86_64 0:9.2.13-1.el7_1             postgresql-libs.x86_64 0:9.2.13-1.el7_1

Complete!
[ec2-user@ip-xxx ~]$ gem install pg -v '0.18.3'
Building native extensions.  This could take a while...
Successfully installed pg-0.18.3
invalid options: -f fivefish
(invalid options are ignored)
Parsing documentation for pg-0.18.3
Installing ri documentation for pg-0.18.3
Done installing documentation for pg after 3 seconds
1 gem installed

再び、データベースをPostgreSQLに指定したアプリケーションを作成してみます。

[ec2-user@ip-xxx ~]$ rails new postgresql -d postgresql
~略~
    conflict  config/secrets.yml

Overwrite /home/ec2-user/postgresql/config/secrets.yml? (enter "h" for help) [Ynaqdh] Y
~略~
Use `bundle show [gemname]` to see where a bundled gem is installed.
         run  bundle exec spring binstub --all
* bin/rake: spring inserted

* bin/rails: spring inserted

途中でsecrets.ymlの競合が起きていましたが、"Y"を選択して上書きしました。、
ここで作成したアプリケーションのdatabase.ymlファイルが、PostgreSQL用の設定項目になっているので、前回作成したsampleアプリケーションのディレクトリにコピーします。

[ec2-user@ip-xxx ~]$ cp sample/config/database.yml sample/config/database.yml.bk
[ec2-user@ip-xxx ~]$ cp postgresql/config/database.yml sample/config/database.yml

次に、PostgreSQLの本体をインストールします。特にバージョンに要求はないので、yumからpostgresql-serverのインストールコマンドによってインストールしました。(ちなみに9.2.13が入りました)

[ec2-user@ip-xxx ~]$ sudo yum install postgresql-server
~略~
Running transaction
  Installing : postgresql-server-9.2.13-1.el7_1.x86_64                                           1/1
  Verifying  : postgresql-server-9.2.13-1.el7_1.x86_64                                           1/1

Installed:
  postgresql-server.x86_64 0:9.2.13-1.el7_1

Complete!

ここからはPostgreSQL自体を利用するための設定をしていきます。まず、postgresユーザのパスワードを設定します。

[ec2-user@ip-xxx ~]$ sudo passwd postgres
Changing password for user postgres.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

次にPostgreSQLを初期化します。初期化のオプションとしては、"--encoding=UTF8 --no-locale"を指定しました。

[ec2-user@ip-xxx ~]$ sudo su postgres
bash-4.2$ cd
bash-4.2$ pwd
/var/lib/pgsql
bash-4.2$ ls

backups  data
bash-4.2$ export PGDATA=/var/lib/pgsql/data

bash-4.2$ initdb --encoding=UTF8 --no-locale
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "C".

The default text search configuration will be set to "english".
~略~
WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    postgres -D /var/lib/pgsql/data
or

    pg_ctl -D /var/lib/pgsql/data -l logfile start

これでPostgreSQLの設定が完了したので、一度PostgreSQLのサーバを起動してみます。

bash-4.2$ exit
exit
[ec2-user@ip-xxx ~]$ sudo service postgresql start
Redirecting to /bin/systemctl start  postgresql.service
[ec2-user@ip-xxx ~]$ sudo su postgres
bash-4.2$ psql
could not change directory to "/home/ec2-user"
psql (9.2.13)
Type "help" for help.


No relations found.
postgres=# \q
bash-4.2$ exit
exit
[ec2-user@ip-xxx ~]$

起動できていることが確認できたので、Railsの設定に戻りましょう。
dabase.ymlを編集し、PostgreSQLに接続できるようにします。

~/sample/config/database.ymlファイル(緑字の部分を変更)
# PostgreSQL. Versions 8.2 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On OS X with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On OS X with MacPorts:
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem 'pg'
#
default: &default
  adapter: postgresql
  encoding: utf8
  # For details on connection pooling, see rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: 5

development:
  <<: *default
  database: sample_development

  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user that initialized the database.
  username: postgres

  # The password associated with the postgres role (username).
  password: postgresユーザのパスワード

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  host: localhost

  # The TCP port the server listens on. Defaults to 5432.
  # If your server runs on a different port number, change accordingly.
  port: 5432

  # Schema search path. The server defaults to $user,public
  #schema_search_path: myapp,sharedapp,public

  # Minimum log levels, in increasing order:
  #   debug5, debug4, debug3, debug2, debug1,
  #   log, notice, warning, error, fatal, and panic
  # Defaults to warning.
  #min_messages: notice

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: sample_test

# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
#   production:
#     url: <%= ENV['DATABASE_URL'] %>
#
production:
  <<: *default
  database: sample_production
  username: postgres
  password: <%= ENV['POSTGRESQL_DATABASE_PASSWORD'] %>

Railsでは3つの環境を想定して開発ができるようになっていますが、データベースも3つ設定できるようになっています。
共通の設定はdefaultセクション、開発環境はdevelopmentセクション、テスト環境はtestセクション、本番環境はproductionセクションにそれぞれ記載します。
なお、上記のdatabase.ymlファイルではdevelopmentセクションで必要な設定は行っていますが、testセクションとproductionセクションは、データベース名とPostgreSQLのユーザ名以外は変更していませんので、テストや本番環境を利用する際は、別途適切な設定を行ってください。

では、PostgreSQLにデータが保存されていることを確認するために、まず適当なモデルとして、Userモデルを作成します。

[ec2-user@ip-xxx sample]$ rails g model user name:string email:string
/home/ec2-user/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/connection_adapters/connection_specification.rb:177:in `rescue in spec': Specified 'postgresql' for database adapter, but the gem is not loaded. Add `gem 'pg'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord). (Gem::LoadError)

Userモデルを作成しようとしましたが、Gemfileに"gem 'pg'"を追記するように要求するエラーが出てしまったので、メッセージ通りにGemfileに追記します。

./Gemfileファイル(緑字の部分を追加・変更)
~略~
# Use sqlite3 as the database for Active Record
#gem 'sqlite3'

gem 'pg'
~略~

また、データベースがSQLiteの場合に必要だった"sqlite3"をコメントアウトしておきました。
改めてUserモデルを作成します。

[ec2-user@ip-xxx sample]$ rails g model user name:string email:string
      invoke  active_record
      create    db/migrate/20151027025328_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml

Userモデルと、Userモデル用のマイグレーションファイルが作成されました。
次にUserモデル用のマイグレーションファイルの内容をDBに反映するために、PostgreSQLにこのアプリケーション用のデータベースを作成します。

[ec2-user@ip-xxx sample]$ rake db:create
FATAL:  role "ec2-user" does not exist
/home/ec2-user/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/connection_adapters/postgresql_adapter.rb:665:in `rescue in connect'
~略~

一部エラーが発生していますが、データベースは作成できました。
※一応、上記のエラーはdatabase.ymlのdefaultセクションに"username"を設定(値はdevelopmentと同じ)にすることで回避できますが、データベースの状態に変わりはありませんでした。

データベースが作成できたので、Userモデル用のテーブルを作成します。

[ec2-user@ip-xxx sample]$ rake db:migrate
== 20151027025328 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0061s
== 20151027025328 CreateUsers: migrated (0.0061s) =============================

成功したようなので、実際にPostgreSQLの状態を確認してみます。

[ec2-user@ip-xxx sample]$ sudo su - postgres
Last login: Tue Oct 27 00:24:59 EDT 2015 on pts/1
-bash-4.2$ psql -d sample_development
psql (9.2.13)
Type "help" for help.

sample_development=# \d
                List of relations
 Schema |       Name        |   Type   |  Owner
--------+-------------------+----------+----------
 public | schema_migrations | table    | postgres
 public | users             | table    | postgres
 public | users_id_seq      | sequence | postgres
(3 rows)

sample_development=# \d users
                                     Table "public.users"
   Column   |            Type             |                     Modifiers
------------+-----------------------------+----------------------------------------------------
 id         | integer                     | not null default nextval('users_id_seq'::regclass)
 name       | character varying           |
 email      | character varying           |
 created_at | timestamp without time zone | not null
 updated_at | timestamp without time zone | not null
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)

しっかりテーブルが作成されていますね。
最後にRailsからDBへのデータ登録ができているかを確認します。

[ec2-user@ip-xxx sample]$ rails c
Loading development environment (Rails 4.2.4)
irb(main):001:0> User.create name: 'inoshita', email: 'inoshita@gmail.com'
   (0.1ms)  BEGIN
  SQL (0.6ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "inoshita"], ["email", "inoshita@gmail.com"], ["created_at", "2015-10-27 04:31:52.475936"], ["updated_at", "2015-10-27 04:31:52.475936"]]
   (3.5ms)  COMMIT
=> #<User id: 1, name: "inoshita", email: "inoshita@gmail.com", created_at: "2015-10-27 04:31:52", updated_at: "2015-10-27 04:31:52">
irb(main):002:0> exit
[ec2-user@ip-xxx sample]$ sudo su - postgres
Last login: Tue Oct 27 00:28:39 EDT 2015 on pts/1
-bash-4.2$ psql -d sample_development
psql (9.2.13)
Type "help" for help.

sample_development=# SELECT * FROM users;
 id |   name   |       email        |         created_at         |         updated_at
----+----------+--------------------+----------------------------+----------------------------
  1 | inoshita | inoshita@gmail.com | 2015-10-27 04:31:52.475936 | 2015-10-27 04:31:52.475936

(1 row)

RailsのコンソールからUserモデルを1件作成し、そのデータがPostgreSQLに登録されていることが分かります。

これでデータベースの差し替えが完了しました!


これでJavaScriptランタイム、データベースの差し替えまで終わりました。

残りのアプリケーションサーバ・Webサーバはメジャーな「unicorn」と「nginx」の組み合わせに差し替えることを予定しています。

前回⇒AWS無料利用枠のインスタンスで、Ruby on Railsの環境を作成してみる①
次回⇒AWS無料利用枠のインスタンスで、Ruby on Railsの環境を作成してみる③

参考にしたサイト

node.jsのインストール手順
http://takafumi-s.hatenablog.com/entry/2015/05/04/122600

PostgreSQLインストール時エラーの解決方法
http://qiita.com/s_osa/items/9b72643c9f7185736395

0 件のコメント:

コメントを投稿