개인적으로 nginx 자체는 매력적이라고 생각했지만, php-fpm 이라던가 uwsgi 같이 웹서버에서 직접 붙지 않고 socket 으로 연결되는 방식이 마음에 들지 않아 잘 사용하지 않았다. 

설정 및 관리가 좀 더 번거롭기도 했고..


이제는 마음에 안들었던 몇가지를 감수하고 장점을 취해보기 위해서 사용해보려고 하는데,  여전히 개떡같은 uWSGI 설정법을 정리해봄.


----------
2020.06.28 gunicorn 설정 추가

uWSGI보다 gunicorn 이 더 좋다고 한다.
나의 경우 웹소켓을 쓰려는데, uWSGI는 제대로 안되고 gunicorn + eventlet 조합으로 해야해서 스택을 변경해봄.


큰 차이는 없다. 거의 비슷...
----------

환경은 Ubuntu 18.04 + Nginx + uWSGI/gunicorn + Python3 + Flask.

이 방법의 최대 장점 중 하나가 프로젝트별로 python 버전에 구애받지 않고 venv 를 전혀 무리 없이 돌릴 수 있다.. 인 것 같은데 난 평소에 그렇게 안쓰고 있으니 일단 생략.


1. 패키지 설치

apt에도 있긴 한데, pip으로 설치해줘도 된다.

pip install uwsgi

pip install gunicorn


2. 프로젝트 wsgi 설정

프로젝트 폴더에 이런식으로 파일을 만든다.

wsgi.py

from flask_app import app

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

uwsgi.ini (gunicorn 의 경우엔 필요없음)

[uwsgi]
#plugin = python3
module = wsgi:app

master = true
processes = 3

socket = /tmp/PROJECT.sock
chmod-socket = 664
vacuum = true

die-on-term = true

plugin = python 은, uwsgi 를 apt로 설치한 경우 필요한 것 같음.


3. systemd unit 생성

/etc/systemd/system/ 경로에 PROJECT.service 로 파일을 만든다.

[Unit]
Description=WSGI instance to serve PROJECT
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/PATH/TO/PROJECT
#Environment="PATH=/PATH/TO/BIN"
#ExecStart=/usr/bin/uwsgi --ini uwsgi.ini
ExecStart=/usr/local/bin/gunicorn -k eventlet -w 3 --bind unix:wsgi.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

뭐 User, Group 이라던가 적당히 해주고, 그 밑에 WorkingDirectory, 환경변수, 실행커맨드 등도 적당히 수정해준다.

gunicorn 도 uwsgi처럼 configuration 파일을 만들어서 할 수 있지만, 명령어로도 충분한 듯...

-k, --worker-class=: 워커 프로세스 종류. sync(기본값), eventlet, gevent 등이 있다.

-w, --workers=: 워커 갯수. 시스템 프로세스 코어당 2~4개가 권장이라는 듯?

-m: unix socket으로 만들 경우 umask


이 후

sudo systemctl enable PROJECT

sudo systemctl start PROJECT

이렇게 자동 실행 설정 및 서비스 시작 해주면 된다.


4. Nginx 설정

sites-available 등의 설명은 생략.


아래와 같이 구성하자. 수정이 필요하다면 적당히 수정...


server {
        listen 80;
        server_name 사이트주소;

        #location / {
        #        include uwsgi_params;
        #        uwsgi_pass unix:///tmp/PROJECT.sock;
        #}
        location / {
                include proxy_params;
                proxy_redirect off;
                proxy_pass http://unix:/PATH/TO/PROJECT/wsgi.sock;
        }
        #location /socket.io {
        #        proxy_pass http://unix:/PATH/TO/PROJECT/wsgi.sock:/socket.io;
        #        include proxy_params;
        #        proxy_http_version 1.1;
        #        proxy_redirect off;
        #        proxy_buffering off;
        #        proxy_set_header Upgrade $http_upgrade;
        #        proxy_set_header Connection "Upgrade";
        #}
        location /static {
                alias /PATH/TO/PROJECT/flask_app/static;
        }
}

업스트림 설정으로 분산화를 하거나, uri 에 따라 다른 프로젝트로 연결하는 것도 가능하다. 이건 내가 쓸일 있을때 수정해둘거임.

uwsgi 는 전용 지시어인 uwsgi_param, uwsgi_pass 를 사용하는데, gunicorn 은 그냥 proxy 관련 지시어들을 사용한다.

소켓을 어디에 만드느냐는 큰 차이 없음.

websocket 을 사용할 경우 주석처리한 것처럼 따로 설정을 해주면 된다.


5. 로그 보기

프로젝트 폴더에 만들었던 uwsgi.ini  에서 log 파일 경로를 지정할 수도 있지만,

sudo journalctl -u PROJECT 로 볼 수도 있다.

uwsgi 관련 로그는 여기에서,

접속 기록이나 파이썬 에러 로그 등은

/var/log/nginx/access.log, /var/log/nginx/error.log 에서 확인할 수 있다. 물론 설정에서 각각 바꿔줬으면 다르겠지?



참고

How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 18.04 (DigitalOcean)

uWSGI documentation

gunicorn documentation

+ Recent posts