Nginxを使ったRailsAppとJenkinsの同棲計画
雑記
おおよそ1年半ぶりの投稿になりますが…… 今回からは色々と挑戦してみたことの技術的備忘録として活用していく予定. (但し予定≒未定)
今回はdeployしたRailsAppとJenkinsを同一server上に置いてやろうぜ!ということをやってみました. ちなみに背景としては
- RailsApp作ってdeployする必要が生じる
- 自宅サーバ置いたら(物理的に)炎上
- cloud借りるか (Microsoft Azureの無料試用期間でVM使うことに)
- どうせならJenkinsでCIやりてぇ
- cloud/VPS高い, 複数借りるのなんてムリィ!
- RailsAppとJenkins共存させよ
目指す構成
目指している構成はこんな感じ. Nginxをreverse proxy serverとして, request URLのprefixで判断し, RailsAppとJenkinsに振り分ける. 理由としては
- 可搬性を考えて(試用期間終わったらどっか他の安いところに移設予定)全部Docker containerにぶち込みたい
- Docker contianer使うならOSはDocker導入が一番楽な(というかdefaultで入ってる)CoreOS使おう
- VPSやCloudのお引越しの度にport設定をし直すの面倒臭い
- Dockerのport forwardingで複数のportを使わない
- 代わりにDocker container内のNginxをプロキシにしてsub directoryでRailsAppとJenkinsを使いわける
早速構成していく
- Core OSにssh login transmission !
- DockerHubからUbuntuのimageをpull
- Dockerでport forwarding(hostの80番とguestの80番を直結), でもってdive!
docker run -d -it -p 80:80 --name hoge ubuntu /bin/bash docker -it exec hoge /bin/bash
- NginxとJenkinsはapt-getなんかを使ってうまいこと入れる (googleれば幾らでも出てくるさ)
- Rails環境もうまいこと入れる (僕の場合はrbenv使ってruby 2.2.0-devとRails5.0.0rcを導入)
- rails newする (ここではRailsAppのdirectoryを/var/app/rails_appとする)
RailsAppとJenkinsをNginxに繋げる
ここでの説明はcurrent directoryを/var/app/rails_appであることを前提として進める.
./config/puma.rbに以下を追記するぅ!
_proj_path = "#{File.expand_path("../..", __FILE__)}" # RailsAppの絶対path _proj_name = File.basename(_proj_path) # RailsAppのおなまえ pidfile "/var/run/#{_proj_name}.pid" # Puma serverが動作しているprocess idを/var/run/rails_app.pidにぶち込むよう指定 (Puma serverはdaemonとして動作させた際に止めたい時, こいつが必要) bind "unix:///var/run/#{_proj_name}.sock" # Puma serverは/var/run/rails_app.sockからHTTP requestを頂く directory _proj_path # working directoryをRailsAppのpathに
/etc/nginx/conf.d/rails_app.conf(/etc/nginx/conf.d/*.confを読むようになっているので, 名前は多分なんでも可)を作成して以下を追記 (serverのIP addressはx.x.x.xを想定)
error_log /var/log/nginx/error.log warn; upstream rails_app { server unix:/var/run/rails_app.sock fail_timeout=0; # /var/run/rails_app.sock を介してPumaとやりとりするよ } server { listen 80; # port80で受け付けるよ server_name x.x.x.x; # x.x.x.xでrequest来たら対応するよ error_page 500 502 503 504 /500.html client_max_body_size 4G; keepalive_timeout 10; include /etc/nginx/mime.types; try_files $uri/index.html $uri @rails_app location /rails_app/ { # URLがhttp://x.x.x.x/rails_app/...だった場合 root /var/app/rails_app/public; # web pageなんかはpublicにぶち込まれるよ proxy_pass http://rails_app; # Pumaに横流しするよ proxy_set_header X-Forwarded-For $proxy_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header off; } location /jenkins/ { # URLがhttp://x.x.x.x/jenkins/...だった場合 proxy_pass http://127.0.0.1:8080; # localhost:8080 (jenkisがわさわさしてるport) にぶん投げるよ } }
ちなみにNginxの設定ファイルが「本来書いてはいけない場所に書いていないか」「文法的に間違っていないか」を確認するには以下を実行するとチェックできる.
nginx -t
次に /etc/default/jenkinsを以下のように変更
# JENKINS_ARGS = "hoge" を以下に変更 (Jenkinsのroot pathをx.x.x/jenkins/に変更) JENKINS_ARGS = "hoge --prefix=/jenkins"
RailsAppのroutingにprefixを追加 (以下の内容を./config/routes.rbを以下のように変更)
Rails.application.routes.draw do # 全部のrouting pathの先頭に/rails_appを装着 scope '/rails_app' do # All routing descriptions end end
このままではJSや画像ファイルなどのassets以下が機能しなくなるので./config/public/environments/development.rb, ./config/public/environments/test.rb, ./config/public/environments/production.rbのRails.application.configure内に以下を追記
config.assets.prefix = '/rails_app/assets'
以下NginxとPuma, JenkinsをContainer起動時に自動で動作するよう設定 (Ubuntuだとchkconfがないっぽいのでsysv-rc-confで代用)
sysv-rc-conf nginx on sysv-rc-conf puma on sysv-rc-conf jenkins on
とするとどうもダメみたいですww バカ正直にcontainer侵入後に以下を実行.
cd /var/app/rails_app bundle exec puma -d # Pumaを停止させる場合は bundle exec pumactl -P /var/run/rails_app stop service jenkins start service nginx start
ちなみに今回はsocket通信を行うWebAppの開発ではないので, Action Cableの設定に関しては考慮していない.
以上, だいたいこんな感じでやってました. 何か不備, 間違いなどがありましたらどんどん指摘してください.
Tips
socket fileが仕事しているかを見るにはcurl --no-buffer -XGET --unix-socket /var/run/rails_app.sock http:/events でsocket fileを叩ける