Search

Release with Flask + Gunicorn + Nginx

카테고리
Back-end
태그
Flask
Nginx
게시일
2022/12/15
수정일
2024/02/24 09:41
시리즈
1 more property

1. 들어가기 앞서

처음에는 Nginx와 uwsgi를 사용하려 했는데, mod_wsgi + Apache2와 다르게 uwsgi는 이전 사용하는 과정에서 서비스를 따로 올려줘야 하는 불편함이 있는 것 같아 아쉬웠다. 혹시 Gunicorn은 이러한 부분이 다르지 않을까 하는 막연한 기대감을 가지고 찾아보았는데 아쉽게도 uwsgi와 동일한 것 같다.
아직 uwsgi 설치 및 사용 옵션에 대한 이해가 부족하여 연구가 더 필요한 상태로 남아 있지만, 대부분 Python web developer분들이 gunicorn을 사용하는 것이 좋다는 의견이 있어서 사용해보기로 마음먹었다.

1.1 환경 구성

운영체제(OS)

Ubuntu 20.04 x 64

프레임워크

Python 3.8.x
Flask

라이브러리

Nginx 1.18
Gunicorn

1.2 참고자료

2. Nginx 설정

2.1 Nginx Install

sudo apt update sudo apt install nginx
Bash
복사

2.2 Firewall setting

sudo ufw app list 명령어로 설정 가능한 방화벽을 확인하면 다음과 같이 나온다.
Available applications: Nginx Full # HTTP, HTTPS all allowed Nginx HTTP # HTTP allowed Nginx HTTPS # HTTPS allowed OpenSSH # SSH allowed
Bash
복사

2.3 Web server checking

systenctl status nginx로 명령어를 확인해보도록 하면 다음과 같이 나온다.
● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2021-07-20 12:23:07 UTC; 19min ago Docs: man:nginx(8) Main PID: 29115 (nginx) Tasks: 2 (limit: 1063) Memory: 4.1M CGroup: /system.slice/nginx.service ├─29115 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; └─29118 nginx: worker process
Bash
복사
위와 같이 Active 상태가 active로 되어 있으면 정상적으로 서비스가 활성화된 상태다.

3. Gunicorn 설정

3.1 Packages installation(Dependency)

sudo apt update sudo apt install -y python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
Bash
복사

3.2 Virtual Env(Option)

sudo apt install -y python3-venv python3 -m venv venv-name source venv-name/bin/activate # leave virtual env : deactivate
Bash
복사

3.3 Gunicorn install

pip install wheel # package에 wheel archive가 없어도 설치되게끔 하기 위해서라는데 일단 설치한다. pip install gunicorn flask which gunicorn # gunicorn 경로 확인하기
Bash
복사

3.4 Entry Point

Gunicorn 실행 체크(update 필요)
gunicorn wsgi:app
Bash
복사

3.5 Service

/etc/systemd/system/ 디렉토리안에 /etc/systemd/system/[service_name].service 만들기
sudo vim /etc/systemd/system/myproject.service
Bash
복사
service file 내의 내용
# /etc/systemd/system/~~~.service [Unit] Description=Gunicorn instance to serve myflask After=network.target [Service] User=flaskuser Group=flaskcert #/home/userme/myproject WorkingDirectory=/var/www/retro #"PATH=/home/userme/myproject/myproject-env/bin" Environment="PATH=/usr/local/bin" #/home/userme/myproject/myproject-env/bin/gunicorn --workers 3 --bind unix:myflask.sock -m 007 wsgi:app # You must chown working directory ExecStart=/usr/local/bin/gunicorn --workers 3 --bind unix:retro.sock -m 007 wsgi:app [Install] WantedBy=multi-user.target
Bash
복사
1.
서비스 재시작
만약 서비스가 재시작 되지 않는다면, systemctl daemon-reload 명령어로 데몬을 초기화 해주도록 한다
2.
ExecStart
서비스를 시작할 때 구동하는 명령어로써, which gunicorn으로 알아낸 /usr/local/bin/gunicorn 경로의 gunicorn 바이너리를 실행하도록 하였다.
Develop setting
만약 개발을 서버를 구동하고자 한다면 service를 stop 하고, gunicorn을 따로 구동하는 것을 추천한다.
$ gunicorn --workers 3 --bind 127.0.0.1:8080 wsgi:app
Bash
복사

3.6 Gunicorn 명령어

wsgi:app
wsgi 파일 내에 있는 app이라는 변수를 통해 flask를 구동하는 구조
workers
프로세스 개수를 정해줌

4. Gunicorn, Nginx 연결하기

Nginx 버전은 1.18버전으로 진행했다. Ubuntu 18.04 버전에서 nginx를 설치했을 때는 어떤 문제인지는 확인하지 못하였으나, $server_name 변수가 정상적으로 작동하지 않은 것을 확인하였다. 따라서 아래의 config 값은 Nginx 1.18 이상의 버전에서 수행하는 것을 추천한다.

4.1 HTTP config

HTTP - Nginx config

# Nginx configuration # /etc/nginx/sites-available/retro.conf # ln -s /etc/nginx/sites-available/retro.conf /etc/nginx/sites-enabled/retro server { listen 80; listen [::]:80; server_name retro.dev.kkamikoon.com; #example.com www.example.com location / { include proxy_params; proxy_pass http://unix:/var/www/retro/retro.sock; } }
Bash
복사

4.2 HTTPS config

HTTPS 설정을 진행하기 전에, 먼저 Certbot 혹은 Letsencrypt을 이용하여 SSL을 발급해야 한다.

apt update

우선 우분투에서 Nginx용 Certbot 설치를 수행한다. Nginx 웹 서버용 Python3를 설치하는 명령어는 아래와 같다.
$ apt update $ apt install certbot python3-certbot-nginx
Bash
복사

Certbot 발급

domain="retro.dev.kkamikoon.com" certbot certonly --webroot --webroot-path=/var/www/letsencrypt -d $domain
Bash
복사

well-known이 있는 곳을 지정

$ mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
Bash
복사

letsencrypt.conf 파일 생성

파일 생성 위치는 다음과 같다.
$ vim /etc/nginx/snippets/letsencrypt.conf
Bash
복사
파일내용은 아래와 같이 작성하고, 생성 위치에 저장하도록 한다.
# file : /etc/nginx/snippets/letsencrypt.conf location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/letsencrypt; }
Bash
복사

HTTPS - Nginx config

# Nginx configuration # /etc/nginx/sites-available/retro.conf # ln -s /etc/nginx/sites-available/retro.conf /etc/nginx/sites-enabled/retro # HTTP - Listen 80 server { listen 80; # listen [::]:80; server_name retro.dev.kkamikoon.com; access_log /var/www/retro/logs/http/access.log; error_log /var/www/retro/logs/http/error.log; # include letsencrypt.conf include /etc/nginx/snippets/letsencrypt.conf; location ~ /\.well-known/acme-challenge/ { allow all; root /var/www/letsencrypt; } location / { return 301 https://$server_name$request_uri; # expires epoch; } } # HTTPS - Listen 443 server { listen 443 ssl; # listen [::]:443 ssl; server_name retro.dev.kkamikoon.com; access_log /var/www/retro/logs/https/access.log; error_log /var/www/retro/logs/https/error.log; # letsencrypt should add new group. # And also chgrp /etc/letsencrypt/live, /etc/letsencrypt/archive # /etc/nginx.conf ==> user [added user name] ssl_certificate /etc/letsencrypt/live/$server_name/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$server_name/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3 SSLv3; ssl_ciphers ALL:!ADH:!EXPORT56:!RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP; ssl_prefer_server_ciphers on; location / { include /etc/nginx/proxy_params; proxy_pass http://unix:/var/www/retro/retro.sock; # proxy_pass http://127.0.0.1:8080; # for dev } }
Bash
복사

4.3 letsencrypt 권한 설정

letsencrypt 권한을 설정은 서비스 실행 시 letsencrypt 접근 부분에서 permission denied가 발생하기도 한다. 이럴 경우 아래와 같은 권한 관리로 해결할 수 있다.

권한 설정

user="flaskuser" group="flaskcert" sudo addgroup $group; sudo adduser $user; sudo adduser $user $group; sudo adduser root $group; # Make the relevant letsencrypt folders owned by said group. sudo chgrp -R $group /etc/letsencrypt/live sudo chgrp -R $group /etc/letsencrypt/archive # sudo chgrp -R flaskcert /etc/letsencrypt/live # sudo chgrp -R flaskcert /etc/letsencrypt/archive # Allow group to open relevant folders sudo chmod -R 750 /etc/letsencrypt/live sudo chmod -R 750 /etc/letsencrypt/archive
Bash
복사

nginx 설정

# file : /etc/nginx/nginx/conf # user www-data; user flaskuser; # <-- change user worker_processes auto; pid /run/nginx.pid; # ...
Bash
복사