今回作成した 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 の各システムの疎通をしました。以上で終了です。お疲れ様でした。
コメント