TIS ENGINEER NOTE

ITエンジニアのためのキャリア向上ノウハウブログ

プログラミング

sinatraでミニマムなWebサービスを公開してみるよ【sinatra + nginx + puma + Capistrano】

更新日:

sinatraとはRubuで作成されたWebフレームワークです。かなりシンプルな構成ですので、Ruby自体の勉強用としてはRailsより向いているかも知れません。

今回はRailsを使うまでもない小規模なWebサイトを作成する機会がありましたので、sinatra + Puma + nginxの構成で公開し、Capistranoでデプロイできるようになるまでを作業をまとめてみました。

Rubyのインストール・公開サーバーの準備等は完了している前提で進めていきます。

作業PCでの作業

まずは開発用のローカル環境下での作業から。

今回はポートフォリオサイトを作るので、アプリケーション名はportfolioです。

まずはディレクトリを作成し、そのディレクトリに移動。その後bundle initでGemfileを生成します。

mkdir portfolio
cd portfolio/
bundle init

そして作成されるGemfileの最後にsinatraを追加します。

gem 'sinatra'

保存したら、以下のコマンドでvendor/bundle配下にgemをインストールします。ローカル環境は極力汚さない。

bundle install --path vendor/bundle

これでローカル開発環境自体は完成となります。

動作確認のために、Rubyファイルを作成し、修正します。

touch main.rb
require 'sinatra'

get '/' do
    "<h1>This is Portfolio<h1>"
end

ひとまずはRubyファイルから直接表示します。最終的にはviewファイルを読み込むように修正します。

そしてsinatraを起動。

bundle exec ruby main.rb

起動されたらブラウザからhttp://localhost:4567/にアクセスしてみましょう。

上記のようにmain.rbに記載した内容が表示されていればOKです。

Gitの初期設定

なにはともあれソースを書いたらバージョン管理。Gitの初期設定を行います。

以降のコマンドは基本的にアプリケーションディレクトリ(今回であればportfolio)配下で実行します。

使用しているPCで初めてGitを使用する場合

git config --global user.name "Your Name"
git config --global user.email your.email@example.com

git init

アプリケーションディレクトリでgit initします。これでportfolio配下がGitによってバージョン管理される対象となります。

git init

gitignoreを設定

git上にアップしたくないファイルを設定します。今回はvendor/bundle配下とbundlerのconfigはアップしないようにします。

touch .gitignore
# Ignore bundler config.
/.bundle

# Ignore bundler gems.
vendor/bundle

/log/*
/tmp/*

add & commit

git add -A
git commit -m "Initialize repository"

リモート設定

Gitリポジトリサービスの登録は済ませておいてください。

Bitbucket,GitHubなりお好みのサービスをどうぞ。

登録しているサービスでリポジトリを作成するとリモート設定のコマンドが表示されますので、そちらを実行しましょう。基本的には以下のような形です。

git remote add origin https://github.com/stobita/portfolio.git
git push -u origin master

以上でバージョン管理の設定は完了です。長丁場ですね。コーヒーでも飲んで一休みしましょう。

サーバーへの配布準備

サーバーに公開するだけなら、作成したファイルをサーバーにコピーしてWebサーバーの準備をするだけですが、それだけだと変更を加えた時に、いちいちコピーし直さなければなりません。それって結構手間になります。

プログラマーは怠惰であれの言葉に則り、Capistranoというツールを使って、自動デプロイを実現しておきます。

Gitリポジトリにpushしたソースを公開サーバーにコピーするという処理をCapistranoにやってもらう流れです。

Webサービスの構築などについては下記サイトを参考に進めました。Railsでの例ではありますが、ディレクトリの設定などは同様に進めることが可能です。Rails、DBの設定の部分などは今回スキップしてしまって構いません。

http://qiita.com/eiei19/items/7c08d358c82cb538def0

まずはGemfileに下記を追加し、bundle installしましょう。

# puma
gem 'puma'

# for deploy
group :development do
  gem 'capistrano',         require: false
  gem 'capistrano-bundler', require: false
  gem 'capistrano3-puma',   require: false
  gem 'capistrano-rbenv',   require: false
end

インストールが完了したら、下記コマンドでCapistranoの初期設定を行いましょう。

bundle exec cap install

コマンドを実行して生成されたCapfileに以下のコマンドを追加しましょう。

require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/puma'

install_plugin Capistrano::Puma

更にconfig/deployファイルも生成されているので、こちらに配布用のコードを書いていきます。

# config valid only for current version of Capistrano
lock "3.9.0"

server '[IPアドレス]', roles: [:app, :web, :db], primary: true
set :repo_url,        'git@github.com:stobita/XXX.git'
set :application,     'portfolio'
set :user,            'deploy_user'
set :ssh_options,     {
  forward_agent: true,
  user: fetch(:user),
  keys: %w(~/.ssh/id_rsa)
}
set :puma_threads,    [4, 16]
set :puma_workers,    0
set :pty,             true
set :use_sudo,        false
set :stage,           :production
set :deploy_via,      :remote_cache
set :deploy_to,       "/var/www/#{fetch(:application)}"
set :puma_bind,       "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state,      "#{shared_path}/tmp/pids/puma.state"
set :puma_pid,        "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log,  "#{release_path}/log/puma.access.log"
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :rbenv_type, :user
set :rbenv_ruby, '2.4.1'
set :linked_dirs, fetch(:linked_dirs, []).push(
  'log',
  'tmp/pids',
  'tmp/cache',
  'tmp/sockets',
  'vendor/bundle',
  'public/system',
  'public/uploads'
)
namespace :puma do
  desc 'Create Directories for Puma Pids and Socket'
  task :make_dirs do
    on roles(:app) do
      execute "mkdir #{shared_path}/tmp/sockets -p"
      execute "mkdir #{shared_path}/tmp/pids -p"
    end
  end
  before :start, :make_dirs
end

namespace :deploy do
  desc "Make sure local git is in sync with remote."
  task :check_revision do
    on roles(:app) do
      unless `git rev-parse HEAD` == `git rev-parse origin/master`
        puts "WARNING: HEAD is not the same as origin/master"
        puts "Run `git push` to sync changes."
        exit
      end
    end
  end

  desc 'Initial Deploy'
  task :initial do
    on roles(:app) do
      before 'deploy:restart', 'puma:start'
      invoke 'deploy'
    end
  end

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      invoke 'puma:restart'
    end
  end

  before :starting,     :check_revision
  after  :finishing,    :cleanup
end

あとは今回アプリケーションをPumaで動かすので、config.ruをアプリケーションディレクトリに作成しておきます。

touch config.ru
require './main'
run Sinatra::Application

ここまで完了したら下記コマンドで配布実行。

bundle exec cap production deploy:initial

権限によってはwww配下にディレクトリが作れないよ!と怒られることもあるので、その場合はサーバーにアクセスし、直接作成しておきましょう。

エラーが発生したり、修正を行った時はリポジトリへのpushを忘れないようにしましょう。特にGemfileを修正した時などは、pushしてから再リトライしないと反映されないので要注意!

正常に終了したら、デプロイは完了です。

nginxの設定

これでアプリケーションが動く仕組みはできましたが、実際にインターネットからアクセスされた時にアプリケーションに繋げる仕組みができていませんので、nginxの設定を行います。nginxのインストールや基本的な設定は上で紹介した記事を参考にしてみてください。

今回は設定ファイルの例だけ書いておきます。

pstream portfolio {
    server unix:/var/www/portfolio/shared/tmp/sockets/portfolio-puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name xxxxx.com
    root /var/www/portfolio/current/public;

    location / {
        proxy_pass http://portfolio;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

設定を記述し終わったら、nginxを起動、または再起動します。

sudo systemctl start nginx
sudo systemctl restart nginx

これで実際にサーバーのドメインまたはIPにアクセスすれば作成したsinatraアプリケーションが表示されます。

これからモリモリカスタマイズしていこうと思います。

閲覧いただき、ありがとうございました。

よく読まれている記事

エンジニア入門

2019/4/23

DMM WEBCAMP(旧:WEBCAMP PRO) - エンジニアとして働きたい人のためのプログラミングスクール

最近のプログラミングスクールは、就業サポート・業務で役立つ教育を掲げているところがかなり多くなってきました。というかこの2つを満たしていないスクールはもはや存在価値が薄くなってきています。 今回はその2本の柱を高いクオリティで実現している DMM WEBCAMP(旧:WEBCAMP PRO)について、現役プログラマの目線から紹介していこうと思います。 このDMM WEBCAMPは総合的に見て、本気でエンジニアを目指そうとする人にとって最有力候補と言えるレベルで非常に優秀なプログラミングスクールです。この根 ...

続きを読む

エンジニア独立

2019/4/15

プログラマーがフリーランスになって独立するために必要なスキル

こんにちは、フリーエンジニアのてぃすです。 ITエンジニアが独立するべきか、しないべきか。昨今のエンジニア・プログラマーの働き方議論において、最もホットなのがこの話題じゃないでしょうか。 賛否については、それぞれの立場や環境によって感情論も混ざって言い分は異なりますし、経験したこともない人の否定意見も飛び交って魑魅魍魎が跳梁跋扈な感じです。 なので今回はそういった賛否ではなく、実際にプログラマーをはじめとするITエンジニアが独立するためにはどの程度のスキル・経歴が必要かについてお話していこうと思います。 ...

続きを読む

エンジニア独立

2018/1/27

エンジニアは報酬・やりがい・成長機会の全てを求めるべき

こんにちは。フリーエンジニアのてぃすです。 僕は働く上で大事な要素となるのは以下の3つであると考えています。 報酬(給与)の額 やりがい 成長機会 で、これは僕のようなエンジニアという職業だと更に重要度が増します。 人手不足・需要拡大の影響もあり、事務や営業などといった非専門的な職業と比べて、選択次第で高収入を目指しやすくなっていますし、キャリア構築の重要性も他の職業よりも高いですからね。 自分の貢献した結果にふさわしい報酬を受け取りたい。 1日8時間、人生の大部分を働くことに費やすことがほとんどのわけで ...

続きを読む

エンジニア独立

2019/5/29

エンジニアが会社員のままでいるのはヤバいなと感じた理由

現在会社員エンジニアからフリーランスエンジニアへの転身を目論んで活動中のてぃすです。 今回は僕が感じた会社に雇われた状態でエンジニアを続けることのデメリットについて語っていきます。 エンジニアは多くの現場で幅広い技術を習得するべきである 会社員としてエンジニアを続けることの最大のマイナスポイント。 それはキャリアのコントロールしにくいという点です。 エンジニアが携わるITの世界というのは、技術の流行り廃りが他の業界に比べて断トツで早いんですよね。 そうなるとその技術で生計を立てていくエンジニアという存在は ...

続きを読む

エンジニア独立

2019/5/30

SIer・SESからWEB系エンジニアにキャリアチェンジする現実的な方法

エクセルで作らされる誰が読むかも分からないドキュメント 月に1回の帰社日 枯れた技術を言われた通りに扱うだけの毎日 スーツ勤務で下級労働者扱い SIer・SES系エンジニアとしての業務経験があり、かつ外の世界を知ったエンジニアから見たSIer・SES系のイメージってこんな感じですよね。 ここで言う外の世界の代表格と言えばWEB系ベンチャーやフリーランス。 カテゴライズの厳密さについては色々と意見はありますが、いわゆる自社サービスで利益を立てている企業と言えば分かりやすいでしょう。 最近ではエンジニアの待遇 ...

続きを読む

-プログラミング
-,

Copyright© TIS ENGINEER NOTE , 2021 All Rights Reserved Powered by AFFINGER5.