Nginxの設定まとめ(Flask+Docker+Gunicorn編)

Flask + docker-composeでのWebアプリ開発にNginxを使用しました。
その際のNginxのポイント、特に設定ファイルについて抜粋してまとめてみました:thumbsup_tone3:

親の記事はコチラとなります。
[■Flask+Docker+Vue.js+AWS...でゲームWebAppを作ってみた](https://qiita.com/akinko/items/404a7312d0fd0dff6df6)

[■Githubにソースコード公開しています](https://github.com/akiraseto/introdon)


# Gunicornと相性良し
Gunicornは**公式ページでNginxの使用を推奨**しています。
https://docs.gunicorn.org/en/stable/deploy.html

Nginxはデフォルトでバッファリングされるので遅いクライアントの影響を受けづらくGunicornのworkerを効率よく捌けるためのようです。特に、worker数(セッション数)が限られる場合は有効。
ちなみに、Apacheサーバはリクエストをバッファリングしないです。
特別な理由が無ければ、WSGIにGunicornを選ぶならNginxの組み合わせが良いです。


# Dockerで動かすときの注意点
foregroundで起動しましょう。
以下は、Dockerfileのコマンド部分です。

```sh

CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]
```
dockerはコマンドをforegroundで実行しないとコンテナが停止します。
nginxはデーモンとして動くので、foregroundで動くように`deamon off`で設定する必要があります。


# サッと設定ファイルをおさらい
簡単に設定ファイルのおさらいします。

モジュールごとに処理を書く
モジュールは次の4つ

- core: プロセス制御、設定ファイルなどに関するモジュール
- event: イベント処理に関するモジュール
- http: httpに関するモジュール
- mail mailに関するモジュール

各設定を決められたコンテキスト内に記述する。
coreモジュールはmainコンテキストに書く。つまり設定ファイルの最上位に記述します。

```conf
coreモジュールの設定

events {
    eventモジュールの設定
}

http {
    httpモジュールの設定
}

mail {
    mailモジュールの設定
}
```


# 設定ファイル(nginx.conf)
Flask + Gunicon +docker-compose環境で構築したNginxの設定ファイルとなります。

```conf

user  nginx;
worker_processes  auto;

# eventsコンテキスト：必須
events {
    worker_connections 512; #コネクション数の制限
}

# httpコンテキスト：必須
http {
    keepalive_timeout 60;
    server_tokens off;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    server {
            listen 80;
            server_name nginx_container;
            charset UTF-8;
            proxy_read_timeout  60s;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_redirect off;
            # 必要、アプリ内リダイレクトした際に、適切なport番号が付与される
            port_in_redirect on;

            # docker-composeでnetworksしているためcontainer名で指定可
            location / {
                proxy_pass http://flask:5000;
            }

    }
}
```

次からはポイントごとに、細かく触れていきます:arrow_down:


## coreモジュール
### worker_processes
実行プロセス数を指定できる。コア数に合わせて設定しておく。
autoにすれば最適なコア数に設定してくれる。
デフォルトは1。


## eventsモジュール
### worker_connections
1つのワーカーが同時に処理できる接続の数を制限します。
仮にプロセスが2つ、コネクションが512なら、最大1024の接続を同時に処理できる計算です。
デフォルトは512。

デフォルトと同値ですが、別の値を検討していたため意図的に残してます。


## httpモジュール
### keepalive_timeout
サーバ側のタイムアウトの秒数となります。
デフォルトは75。


### server_tokens
エラーページのフッターにNginxのバージョンを表示するかどうかの設定。
不要な上に、セキュリティ的に外しておくべき。`off`にします。


### proxy_set_header
バックエンドサーバに送信するヘッダを再定義する。


### proxy_redirect
バックエンドサーバのリダイレクト時の Location ヘッダです。
on なら proxy_pass をホスト名として、off ならサーバの指示通りにリダイレクト。
locationヘッダ内でコンテナ構成であるホスト名を晒す必要もないので、`off`にします。


### port_in_redirect
適切なport番号が付与されます。
アプリ内でのリダイレクトした際に、これを設定してないとAppコンテナのPORTが使用されます。Nginxのポート(80)と、Appコンテナのポート(5000)が異なるため、毎回リダイレクトが失敗します。
Flaskでridirectを利用するならコチラの設定は必須です。


### location
Flaskが実行されているAppコンテナとは以下で接続しています。
`proxy_pass http://flask:5000;`

これは、docker-composeの設定で接続元のflaskコンテナが以下の設定をしているためです。

```yml
#抜粋

flask:
    build: .
    container_name: flask

    #省略

    networks:
      - front
    expose:
      - 5000
```
front networkでnginxと接続しています。そのためcontainer_nameの`flask`で接続することができます。また、`expose 5000`で、接続コンテナにPORTを開いているので、port番号を`5000`で接続します。


# おわりに
最低限の内容でした、まだまだ勉強不足です。:scream:
Nginx勉強すると、トラフィックの捌き方、負荷の分散といろいろ身に付きますので費用対効果高そうです。
最後まで読んでいただきありがとうございました。:raised_hands_tone3: