巨人の足元でたじlog

そうして言葉を軽んじるから――― 君は私の言葉を聞き逃す

nginxとかrailsとかdocker-composeの備忘録

nginxのインストール

$ sudo yum update -y
$ sudo yum install -y nginx
$ nginx -v 
nginx version: nginx/1.12.1
$ sudo service nginx status
nginx is stopped
$  sudo service nginx start
Starting nginx:                                            [  OK  ]

xxx.xxx.xxx.xxxにアクセス。
(セキュリティグループで80番ポートを開放しておく)

無事あのページが表示されました。
f:id:benzenetarou:20180728001121p:plain

コンテンツの変更

nginxのドキュメントルートはここらしい /usr/share/nginx/html

参考: [備忘録]nginxのドキュメントルート

ということで、ドキュメントルートのコンテンツを変更してみる。

$ ls -al /usr/share/nginx/html/
合計 24
drwxr-xr-x 2 root root 4096  7月 27 15:06 .
drwxr-xr-x 3 root root 4096  7月 27 15:06 ..
-rw-r--r-- 1 root root 3696  9月 11  2017 404.html
-rw-r--r-- 1 root root 3738  9月 11  2017 50x.html
-rw-r--r-- 1 root root 3770  9月 11  2017 index.html
-rw-r--r-- 1 root root  368  9月 11  2017 nginx-logo.png
lrwxrwxrwx 1 root root   32  7月 27 15:06 poweredby.png -> /usr/share/pixmaps/poweredby.png

特にパスを指定しない場合は、index.htmlが表示される。

$ sudo vi /usr/share/nginx/html/hoge.html

このファイルにhogeと書き込んでおく。
そしてxxx.xxx.xxx.xxx/hoge.htmlにアクセスする。

すると、hogeと表示された。

さて、これで /usr/share/nginx/html/hoge.htmlがドキュメントルートということが確認できたが、この設定ファイルはどこに書いてあるんだろうか。

設定ファイルを探してみる。 どうやらたくさんあるみたいだ。

# ls -al /etc/nginx
total 76
drwxr-xr-x  4 root root 4096 Jul 27 15:06 .
drwxr-xr-x 79 root root 4096 Jul 27 15:06 ..
drwxr-xr-x  2 root root 4096 Jul 27 15:06 conf.d
drwxr-xr-x  2 root root 4096 Sep 11  2017 default.d
-rw-r--r--  1 root root 1077 Sep 11  2017 fastcgi.conf
-rw-r--r--  1 root root 1077 Sep 11  2017 fastcgi.conf.default
-rw-r--r--  1 root root 1007 Sep 11  2017 fastcgi_params
-rw-r--r--  1 root root 1007 Sep 11  2017 fastcgi_params.default
-rw-r--r--  1 root root 2837 Sep 11  2017 koi-utf
-rw-r--r--  1 root root 2223 Sep 11  2017 koi-win
-rw-r--r--  1 root root 3957 Sep 11  2017 mime.types
-rw-r--r--  1 root root 3957 Sep 11  2017 mime.types.default
-rw-r--r--  1 root root 3734 Sep 11  2017 nginx.conf
-rw-r--r--  1 root root 2656 Sep 11  2017 nginx.conf.default
-rw-r--r--  1 root root  636 Sep 11  2017 scgi_params
-rw-r--r--  1 root root  636 Sep 11  2017 scgi_params.default
-rw-r--r--  1 root root  664 Sep 11  2017 uwsgi_params
-rw-r--r--  1 root root  664 Sep 11  2017 uwsgi_params.default
-rw-r--r--  1 root root 3610 Sep 11  2017 win-utf

たくさんあって、どこがそれらしいか探すのが面倒臭そうだ。
とりあえず現在は/usr/share/nginx/html/がドキュメントルートになっているので、その文字列をこのディレクトリ以下から再帰的に検索して探す。

【Linux】複数あるファイルの中から特定の文字列を検索するコマンド | かわたま.net より、いい感じのコマンド。

# find ./* -type f -print | xargs grep 'nginx/html'
./nginx.conf:        root         /usr/share/nginx/html;
./nginx.conf:#        root         /usr/share/nginx/html;

見つかった。
結局モロに一番怪しそうな/etc/nginx/nginx.confにあった。 コメント行をエスケープして見てみると、そこまでバカ多くなさそうで安心。

$ cat nginx.conf | grep -v -E "^\s*#" | grep -v -E "^\s*$"
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;
}
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;
    index   index.html index.htm;
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  localhost;
        root         /usr/share/nginx/html;
        include /etc/nginx/default.d/*.conf;
        location / {
        }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

試しにlisten 80 default_server;の部分を80→8081に変えてみる。

sudo service nginx configtest
sudo service nginx restart

すると、ポート指定なしでアクセスできず、8081ポートでアクセスできた。なるほど。

nginxとプロセスとかの話

nginxをかませることのメリットは、大量のアクセスをさばけるだとか、リダイレクトやらなんやらができるみたいな認識だ。
聞きかじった知識では、プロセスがコアの数だけうんぬんみたいな話だった。
まずは、nginxを挟まないとプロセスが1個だけだよ〜ってのを確認したい。
pythonの軽量フレームワークのflaskで確認する。

これの環境構築は

benzenetarou.hatenablog.com

ここにサクッと書いてある。
今回は、hello.pyを以下のようにする。

import time
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello'

@app.route('/sleep')
def sleep():
    time.sleep(2)
    return 'sleep'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

これで、起動する。

python36 hello.py
 * Serving Flask app "hello" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

これをローカルからcurlする。 2つのシェルスクリプトを用意する。
sleep.sh

echo `date '+%y/%m/%d %H:%M:%S'`
echo ""
for i in `seq 0 99`
do
    curl http://xxx.xxx.xxx.xxx:5000/sleep
done
echo ""
echo `date '+%y/%m/%d %H:%M:%S'`

loop.sh

echo `date '+%y/%m/%d %H:%M:%S'`
echo ""
for i in `seq 0 99`
do
  curl http://xxx.xxx.xxx.xxx:5000
done
echo ""
echo `date '+%y/%m/%d %H:%M:%S'`

これをターミナルを2つ開いて同時に実行させる。 ちなみにloop.shだけを実行すると、

18/07/28 01:39:14

HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello
18/07/28 01:39:20

となった。(使っているwifiは36.4Mbpsをマークしていた)

もしflaskが1リクエストずつしか返せないとしたら、sleep()の処理をしている間はhello()の処理もできないので、sleepの遅さに引きずられてloopも遅くなるはず。

実行結果は、 sleepがちんたらやっている間、loopはloopで勝手にリクエスト&レスポンスを繰り返していて、通常時と殆ど変わらない速さで終了した。

と、いうことは? Flaskはnginxとかかまさなくても、複数の処理を同時にできる。と。
あっれーnginxいらなくね?ってなってしまったので、ちゃんと調べる。

qiita.com

オイオイオイオイホントかよ。。

この記事が言うことにゃあ "デフォルトでは"一つのリクエストのレスポンスを返すまでは、次のリクエストの処理を始められないとな。
ソースコードまんま引用させていただきます。

from flask import Flask, make_response, jsonify
import time

# flask
app = Flask(__name__)

# rest api
@app.route('/hello/<string:value>', methods=['GET'])
def hello(value):
    result = 'hello {0}'.format(value)
    print('[start] ' + result)

    time.sleep(10)

    print('[end] ' + result)
    return(make_response(result))

# main
if __name__ == "__main__":
    # 同時アクセスができない(並列処理が不可能)
    # app.run(host='localhost', port=3000)

    # 同時アクセスができる(並列処理が可能)
    app.run(host='localhost', port=3000 threaded=True)

オイオイオイオイ、あいつ死ぬぜ。
結果、どうやら仕様が変わったようで、デフォルトではthreaded=Trueになっているようでした。
逆にthreaded=Trueと指定することで、リクエストからレスポンスを返すまでが詰まると、どんどんキューが溜まっていくという挙動を確認できた。

ただ、これにnginxをかませてもボトルネックはアプリケーション・サーバーのflaskになると思うので、nginxをかませる利点がまだ腑に落ちない。
本でも買ってみるかな。

と、そもそもなんでこんなnginxについて調べているのかを見失っていた。。。

いいのや、別にC10K問題とか、個人開発では直面せんやろ…
直面できたらラッキーだわむしろ。
ということで、これはタイムカプセル案件にしておく。

本来やりたかったことは、
nginx + unicorn + rails (puma?)をdocker-composeでec2上でデプロイすること。
その前段として、dockerを使わないで上記のデプロイ環境を構築すること。
そして、その前段としてnginxの概要を理解することだった。
いままでapacheですら簡単にしか触ったことなかったし、その使い方も、適当にドキュメントルートをルートディレクトリとして、localのmac動かす感覚でrails -s コマンド叩くみたいな多分間違っているやり方だったっと思う。
ので、ちゃんとウェブサーバーとアプリケーションサーバーの間の設定とか理解しときたい。
一旦、本来やりたいnginx + unicorn + railsをやりにいく。

実際にインストール

https://qiita.com/eighty8/items/0288ab9c127ddb683315 とりあえずこの手順をほとんど思考停止設定していけば、「nginx + unicorn + rails + mysql on docker」が構築できて、実際にサーバーにポート指定なしでアクセスできて、scaffoldまでできる。

これで実行環境は良しとして、課題は
1. 現行動いているソースコードをどうやってここに反映するか
2. この手順ではmysqlを使っているが、現行のシステムではpostgresqlを使っているので、その差異をどうやって吸収するか
3. そもそもDBをどうやって移行するか

この3点を解決したい。
といったところで、明日にする。