Nginx + Gunicorn + Flaskの環境構築を行った際のメモ。
流れは、Client => Nginx => Gunicorn => Flask
NginxとGunicornの接続については以下のサイトが参考になった。
Nginx + Gunicorn + Django + Aurora (MySQL) の本番環境をAnsible Playbookで構成する - Qiita
NginxとGunicornの接続をソケットからHTTPに変更した - Qiita
Gunicorn用のSystemdソケットとサービスファイルの作成 - Qiita
Socket接続とHTTP接続があるが、
NginxとGunicornを別々のサーバ上に分けて設定しない限りは、Socket接続のほうが早いので、Socket接続を採用する。
Nginxの設定
やり方は省略するが、nginx用のユーザである「nginx」ユーザを作成する。
そして以下のページと同じ設定を行い、
upstreamの箇所を以下のように変更するだけ。
upstream app_server {
server unix:/run/gunicorn/socket fail_timeout=0;
}
Gunicornの設定
Pythonの環境は以下のページを参考に「pyenv + pipenv」で構築
thoames.hatenadiary.jp
defaults/main.yml (※gunicorn_app_pathは任意)
---
gunicorn_version: "20.0.4"
gunicorn_bin: "{{ working_direcory }}/.venv/bin/gunicorn"
gunicorn_app_name: "gunicorn"
gunicorn_app_path: "run:app" # app module in run.py
gunicorn_run_dir: "/run/gunicorn"
gunicorn_config_dir: "/etc/gunicorn"
gunicorn_socket: "gunicorn.socket"
gunicorn_bind: "unix:/run/{{gunicorn_app_name}}/socket"
gunicorn_user: "{{ admin_user }}"
gunicorn_dynamic_workers: False
gunicorn_cpu_coefficient: 2
gunicorn_workers: 1
# [Log]: use nginx log functions
gunicorn_loglevel: False
gunicorn_errorlog: False
gunicorn_accesslog: False
# gunicorn_loglevel: "info"
# gunicorn_errorlog: "/var/log/gunicorn/error.log"
# gunicorn_accesslog: "/var/log/gunicorn/access.log"
gunicorn_reload: False # only for 'development'
gunicorn_timeout: 600 # because of scraping
tasks/main.yml
---
- name: Check exist pipenv command
shell: type pipenv
register: exist_pipenv
failed_when: false
tags: gunicorn
- name: Install Gunicorn
shell: bash -lc "pipenv install gunicorn=={{ gunicorn_version }}"
args:
chdir: "{{ working_direcory }}"
when: exist_pipenv is success
tags: gunicorn
- name: Make gunicorn config directory
file: path={{ gunicorn_config_dir }} state=directory
tags: [gunicorn, gunicorn_config]
- name: Configure gunicorn
template: src=gunicorn.py.j2 dest={{ gunicorn_config_dir }}/{{ gunicorn_app_name }}.py
notify:
- restart socket
- restart gunicorn
tags: [gunicorn, gunicorn_config]
- name: Configure gunicorn socket
template: src=gunicorn.socket.j2 dest=/etc/systemd/system/{{ gunicorn_socket }}
notify:
- restart socket
- restart gunicorn
tags: [gunicorn, gunicorn_config]
- name: Configure systemd service
template: src=systemd.conf.j2 dest=/etc/systemd/system/{{ gunicorn_app_name }}.service mode="0755"
notify:
- restart socket
- restart gunicorn
tags: [gunicorn, gunicorn_config]
- name: Enable gunicorn service
service: name="{{ gunicorn_app_name }}.service" enabled=yes
tags: [gunicorn, gunicorn_config]
handlers/main.yml
---
- name: restart gunicorn
service: name={{ gunicorn_app_name }} state=restarted daemon_reload=yes
- name: restart socket
systemd: name={{gunicorn_app_name}}.socket enabled=yes state=restarted daemon_reload=yes
gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream={{ gunicorn_run_dir }}/socket
[Install]
WantedBy=sockets.targetgunicorn.py (gunicorn用の設定ファイル)
import multiprocessing
bind = '{{ gunicorn_bind }}'
timeout = {{gunicorn_timeout}}
{% if gunicorn_loglevel %}
loglevel = '{{ gunicorn_loglevel }}'
{% endif %}
{% if gunicorn_accesslog %}
accesslog = '{{ gunicorn_accesslog }}'
{% endif %}
{% if gunicorn_errorlog %}
errorlog = '{{ gunicorn_errorlog }}'
{% endif %}
reload = {% if gunicorn_reload %}True{% else %}False{% endif %}
{% if gunicorn_dynamic_workers %}
workers = ({{gunicorn_cpu_coefficient}} * multiprocessing.cpu_count()) + 1
{% else %}
workers = {{gunicorn_workers}}
{% endif %}
gunicorn.service (systemd用のサービス設定)
[Unit]
Description = {{ gunicorn_app_name }}
Requires = {{ gunicorn_socket }}
After = network.target
[Service]
PermissionsStartOnly = true
User = {{ gunicorn_user }}
Group = {{ gunicorn_user }}
RuntimeDirectory = {{ gunicorn_app_name }}
PIDFile = {{ gunicorn_run_dir }}/{{ gunicorn_app_name }}.pid
WorkingDirectory = {{ working_direcory }}
ExecStart = {{ gunicorn_bin }} --pid {{ gunicorn_run_dir }}/{{ gunicorn_app_name }}.pid \
--config {{ gunicorn_config_dir }}/{{ gunicorn_app_name }}.py \
{{ gunicorn_app_path }}
ExecReload = /bin/kill -s HUP $MAINPID
ExecStop = /bin/kill -s TERM $MAINPID
PrivateTmp = true
[Install]
WantedBy = multi-user.target
[その他参考]
GitHub - azavea/ansible-gunicorn: An Ansible role for installing and configuring gunicorn.
Django + Nginx + Gunicorn でアプリケーションを立ち上げる | WEBカーテンコール
ansible/gunicorn.service.j2 at master · UTNkar/ansible · GitHub
Deploying Gunicorn — Gunicorn 20.0.4 documentation