todoList管理アプリを作ってみる①

nginx - sinatra - mysql

今回作成した Webサーバ の構成は,
 サーバ
  OS : ubuntu 22.04 LTS
  Webサーバ : nginx
  APサーバ : ruby ( sinatra )
  DB : mysql
  アプリ : todoList 管理アプリ
 開発環境
  mac

 です。少しずつ機能を追加していく予定です。

0 はじめに
 表記方法について
 @server:~$ サーバ機でログインしている状態です。
 @server(ssh):~$ 開発機等から ssh を利用してサーバにログインしている状態です。
 @dev:~$ 開発機のコンソールです。
 なお ~ はホームディレクトリを示します。

1 環境構築
1-1 ubuntu 22.04 サーバの準備
 ハードはクラウドを利用せず,ローカルネットワークに ubuntu 22.04 を準備しました。
 接続は ssh で行いたいのでまず ssh 接続できるよう準備します。
 準備が終わるまではサーバ機でログインします。
 サーバのターミナルで自身のIPアドレスと ssh サーバの起動状況を確認します。

( input )
@server:~$ ip a

 このコマンドの出力結果を見ていると inet 192.168.0.11/24 の表示がありました。私の環境ではサーバの ip は 192.168.0.11 のようです。次に ssh サーバの稼働状況を確認します。

( input )
@server:~$ ss -atn

( output )
State  Recv-Q Send-Q Local Address:Port  Peer Address:PortProcess
LISTEN 0      128          0.0.0.0:22         0.0.0.0:*          

 22 番ポートの待ち受けがあれば ssh サーバが稼働してます。もし、22 番ポートの待ち受けがなかった場合は openssh-server をインストールしてください。

( input )
@server:~$ sudo apt update
@server:~$ sudo apt install -y openssh-server

 インストールできれば完了です。念の為 ss -atn コマンドを実行してみてください。待ち受けに 22 番ポートがあるはずです。

1-2 ssh 接続の準備
 ssh とは Secure SHell の略で、リモートのコンピュータと暗号化された通信を行うことができるプロトコルです。ssh の認証方式は主なもので,パスワード方式と公開鍵認証方式があります。公開鍵方式の方が相対的に安全性が高いため,ここでは公開鍵認証方式で接続できるよう準備します。
 手順1 開発環境側で鍵ファイルを作成します。
 手順2 生成した鍵ペアの公開鍵をサーバに転送します。
 手順3 接続します。

( input - 手順1 )
@dev:~$ ssh-keygen -t ed25519

( input - 手順2 )
@dev:~$ ssh-copy-id -i ~/.ssh/id_ed25519.pub yosuke@192.168.0.11

( input - 手順3 )
@dev:~$ ssh yosuke@192.168.0.11

 リモートで接続する準備が完了です。今後は ssh でサーバに接続し環境の構築を行います。

2 サーバのセットアップ
2-1 ruby をインストール
 作成しようとしている機能は動的なページを含むため、AP サーバとして ruby をインストールします。AP サーバ ( アプリケーションサーバ ) とは、Webアプリケーションの実行環境として、動的なコンテンツの生成等を行うサーバです。

( input )
@server(ssh):~$ sudo apt update
@server(ssh):~$ sudo apt install -y ruby ruby-bundler
@server(ssh):~$ ruby -v

 適切に ruby のバージョンが表示されれば ruby のインストールは完了です。次に ruby の作業ディレクトリを決め,移動します ( ここでは /home/user/ruby-work とします )

( input )
@server(ssh):~$ cd /home/user
@server(ssh):~$ mkdir ruby-work

 作業ディレクトリに移動したら bundler を初期化します。bundler は gem と呼ばれる ruby のライブラリ同士の互換性を保ちながら gem のインストールをしてくれるツールです。

( input )
@server(ssh):~/ruby-work$ bundle init

 init コマンドで Gemfile が生成されるので,ここにインストールする sinatra の情報を記載をし、インストールを行います。

( input )
@server(ssh):~/ruby-work$ vi Gemfile

( input - Gemfile に追記する内容 )
gem 'sinatra', '~> 2.2', '>= 2.2.4'

( input )
@server(ssh):~/ruby-work$ bundle install

 と追記しインストールを行います。( 表記方法についてはこちら )
 インストールが完了したら、簡単な動作確認を行います。開発環境で次の ruby ファイルを作成し、scpコマンドでサーバにアップロードします。( vi 等で直接作成してももちろんOKです )

require 'sinatra'

# /api/hello へ get リクエスト があった場合の処理
get '/api/hello' do
	{
		message: 'hello world!'
	}.to_json # 'hello world' の文字列を json 形式で返します。
end
( input )
@dev:~$ scp app.rb yosuke@192.168.0.11:~/ruby-work/

 アップロードできたら ruby を起動します。

( input )
@server(ssh):~/ruby-work$ ruby app.rb

( output )
..
[yyyy-mm-dd hh:mm:ss] INFO  WEBrick::HTTPServer#start: pid=1794 port=4567

 ruby から sinatra が起動し 4567 ポートで待ち受けをしている状態となりました。では、’サーバ’に接続して別の terminal から port=4567 を指定して動作確認します。
 開発環境から新しいターミナルを起動します。動作確認は curl コマンドを使用します。curl コマンドはサーバからの返信をそのままテキストとして表示してくれます。インストールして使ってみます。また、ポートの待ち受けも確認してみます。

( input - curl がインストールされているか確認します )
@server(ssh):~$ which curl

( output - 何も表示されなければインストールされていません。)

( input - インストールされていない場合のみ )
@server(ssh):~$ sudo apt install -y curl

( input )
@server(ssh):~$ curl localhost:4567/api/hello

 端末に {message”:”hello world!”} と表示されれば成功です。では次に開発機からも確認してみます。
※ruby のバージョンによっては、アプリケーションサーバが削除されており,別途用意する必要があります。Gemfile に gem “puma” を追記するなどする必要があります。
※https://bugs.ruby-lang.org/issues/17303

( input )
@dev:~$ curl 192.168.11.26:4567/api/hello

( output )
curl: (7) Failed to connect to 192.168.0.11 port 4567 after x ms: Couldn't connect to server

 接続に失敗しました。原因を調べてみます。

( input )
@server(ssh):~$ ss -atn

( output )
State   Recv-Q   Send-Q     Local Address:Port     Peer Address:Port   Process  
LISTEN  0        4096           127.0.0.1:4567          0.0.0.0:*

 待ち受け状況に 127.0.0.1:4567 とあります。127.0.0.1 はループバックアドレスと言われる特別な ip で、自身からのアクセスしか受け付けないことを示します。このため、外部 ( 開発機 ) からのアクセスができなかったようです。では sinatra のファイルを次のように修正します。

require 'sinatra'

# 待ち受けの ip を 0.0.0.0 に指定します。
set :bind, '0.0.0.0'

# /api/hello へ get リクエスト があった場合の処理
get '/api/hello' do
	{
		message: 'hello world!'
	}.to_json # 'hello world' の文字列を json 形式で返します。
end

 set :bind, ‘0.0.0.0’ の記述を追加しています。この設定は待ち受ける ip を 0.0.0.0 に設定します。このアドレスも 全ての ip を示す特別な ip です。この設定にしておけば、有効な全てのネットワークからのリクエストに答えます。再度サーバにアップロードして動作確認をしてみます。

( input )
@dev:~$ scp app.rb yosuke@192.168.11.26:~/ruby-work/
@dev:~$ curl 192.168.11.26:4567/api/hello

 {message”:”hello world!”} と表示されました。開発機のブラウザでも試してみます。
 192.168.11.26:4567/api/hello と直接入力して表示を確認してみます。成功しましたか?

2-2 mysqlのセットアップ

 mysql をインストールして稼働を確認します。

@server(ssh):~$ sudo apt update
@server(ssh):~$ sudo apt install -y mysql-server
@server(ssh):~$ systemctl status mysql

 active (running) の表記が確認できたら,ログインの初期情報を確認します。

@server(ssh):~$ sudo cat /etc/mysql/debian.cnf

 ここに記載されている user と password を使ってログインしてみます。

@server(ssh):~$ mysql -u debian-sys-maint -p

 パスワードを入力してログインし,今回の使用する database を設定します。(スクリプトを流します。)

create database todoList;
use todoList;

create table todoList (
    id int primary key auto_increment
    , todo varchar( 255 )
);

insert into todoList ( todo ) values ( '英語宿題 p7 ~ p9' );
create user 'todoList'@'%' identified by 'password';
grant select,insert,update,delete on todoList.* to 'todoList'@'%';

exit;

2-3 sinatra から mysql への疎通

 sinatra から mysql へアクセスするための準備として Gemfile に 次のとおり追記します。

gem 'mysql2', '0.5.2'

 必要な依存ライブラリとともにインストールを行います。

@server(ssh):~$ sudo apt install -y ruby-dev build-essential libmariadb-dev
@server(ssh):~$ sudo bundle install

 先ほど作った app.rb に mysql との連携のための設定情報を記述し、サーバに転送してから実行してみます。

require 'sinatra'
require 'mysql2'

# 待ち受けの ip を 0.0.0.0 に指定します。
set :bind, '0.0.0.0'

# /api/hello へ getリクエスト があった場合の処理
get '/api/hello' do
    client = connect
    result_set = client.query( 'select id , todo from todoList' )
    datas = result_set.map do |row| {
    id: row['id'],
    todo: row['todo']
}
end

client.close

{
    datas: datas
}.to_json
end

def connect
    Mysql2::Client.new(
    :host => "localhost",
    :database => "todoList",
    :username => "todoList",
    :password => 'password',
    :connect_timeout => 5
)
end
( input )
@dev:~$ scp app.rb yosuke@192.168.0.11:~/ruby-work

( input - ssh でサーバに接続し ruby を起動 )
@server(ssh):~/ruby-work$ ruby app.rb

( input - 新しい console を立ち上げて実行 )
@dev:~$ curl 192.168.0.11:4567/api/hello

 mysql に登録した value1 , value2 が json で表示されれば完了です。

2-4 nginx のセットアップ
 念のため ss -atn コマンドで 80 番ポートの待ち受けがないことを確認します。(もしあれば web サーバがインストールされています。)

@server(ssh):~$ sudo apt update
@server(ssh):~$ sudo apt install -y nginx

 curl コマンドで起動を確認します。curl コマンドはサーバからの返信をそのままテキストとして表示してくれます。インストールして使ってみます。また、ポートの待ち受けも確認してみます。

( input )
@server(ssh):~$ curl hocalhost

( output - Welcome to nginx! と表示されれば成功です )
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title> ...

( input )
@server(ssh):~$ ss -atn

( output )
State      Recv-Q  Send-Q   Local Address:Port      Peer Address:Port  Process  
LISTEN     0       128            0.0.0.0:22             0.0.0.0:*
LISTEN     0       511            0.0.0.0:80             0.0.0.0:*
...

2-5 リバースプロキシ ( upstream ) の設定
 リバースプロキシは、クライアントからの要求をさらに別のサーバに転送する役割を持つサーバのことを指します。ここでは nginx がリバースプロキシの役割を果たし ruby ( sinatra ) にリクエストを転送します。こうすることで、直接 ruby ( sinatra ) にリクエストを送る必要がなくなるため、一般的な html の待ち受けポートである 80 を使用して ruby ( sinatra ) を利用することができるようになります。次の場所にあるファイルに設定を追加します。
 /etc/nginx/sites-enabled/default に次のように追記します。( sudo で編集します )

location /api/ {
	proxy_pass http://localhost:4567;
}

 保存したら nginx の設定をリロードし curl コマンドで動作を確認してみます。

@server(ssh):~$ sudo systemctl reload nginx
@server(ssh):~$ curl http://localhost/api/hello

 直接ポート番号 4567 を指定したときと同じ結果の {message”:”hello world!”} と表示されれば疎通完了です。開発機のサーバからも動作確認してみましょう。

 開発機のブラウザで http://192.168.0.11/api/hello と入力してください。mysql に登録したデータがブラウザ上で json形式として表示されたでしょうか。
 第1回目では nginx – ruby ( sinatra ) – mysql の各システムの疎通をしました。以上で終了です。お疲れ様でした。

コメント

タイトルとURLをコピーしました