nginx 와 python web application 연동
이번 장에서는 python flask 로 만든 web app 를 구성하고 nginx 와 연동해 보도록 하겠습니다.
사전에 python3 가 설치되어 있어야 합니다.
flask project 생성
먼저 flask app project 를 생성해 보도록 하겠습니다.
"flask-project" 라는 폴더를 생성하고 Virtual Env 를 설치해 줍니다.
$ mkdir flask-project $ cd flask-project $ python3 -m venv venv
venv 를 활성화합니다.
$ . venv/bin/activate
이제 Python Flask 를 사용자 모드로 설치합니다.
$ pip install Flask --user
flask app 구동
다음 내용으로 테스트용 web app 을 만들어서 hello.py 로 저장합니다.
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return b"Index Page" @app.route('/hello') def hello(): return b"Hello, World!\n"
이제 python flask 에 내장된 기본 웹 서버를 실행해서 테스트 해봅니다.
FLASK_APP=hello flask run --host 127.0.0.1 --port 8888
브라우저에서 연결한 후에 / 와 /hello 라우팅에 연결해서 정상 작동 여부를 확인합니다.
방화벽때문에 연결이 안 될 경우 방화벽을 여는 것보다는 서버에서 curl 등 커맨드에서 연결 확인하는 게 좋습니다.
$ curl -v localhost:8888/hello
gunicorn 연동
개발할때는 flask 에 내장된 웹 서버를 사용해서 개발/테스트를 해도 되지만 운영 환경에서는 성능 문제때문에 전용 WAS 를 사용해야 합니다.
python 은 web server와 python web application 간 연동을 위한 WSGI(Web Server Gateway Interface) 규격이 있으므로 이를 구현한 전용 WAS 를 구동하고 이를 웹 서버와 연동하면 됩니다.
많이 사용되는 python WAS 중 하나는 Green Unicorn 의 약자인 규니콘(gunicorn) 으로 미리 여러 개의 worker 를 만들어 놓은 후에 서비스하는 pre-fork 모델을 사용하고 있습니다.
먼저 다음 명령어로 gunicorn 을 설치합니다.
pip install gunicorn
현재 폴더에 myapp.py 를 만들고 다음 내용을 추가합니다.
def app(environ, start_response): data = b"Hello, World!\n" start_response("200 OK", [ ("Content-Type", "text/plain"), ("Content-Length", str(len(data))) ]) return iter([data])
이제 gunicorn 을 구동합니다.
gunicorn -w 1 myapp:app -b 127.0.0.1:8888
제대로 동작하는지 확인하기 위해 curl 로 요청해 봅니다.
curl -I 127.0.0.1:8888
nginx 연동
이제 다른 WAS 와 연결하듯이 WSGI 를 연결할 때 proxy 를 사용하면 됩니다.
upstream app_server { # fail_timeout=0 means we always retry an upstream even if it failed # to return a good HTTP response # for UNIX domain socket setups # server unix:/tmp/gunicorn.sock fail_timeout=0; # for a TCP configuration server 127.0.0.1:8888 fail_timeout=0; } server { # use 'listen 80 deferred;' for Linux # use 'listen 80 accept_filter=httpready;' for FreeBSD listen 80; client_max_body_size 4G; # set the correct host(s) for your site server_name example.com www.example.com; keepalive_timeout 5; # path for static files root /path/to/app/current/public; location / { # checks for static file, if not found proxy to app try_files $uri @proxy_to_app; } location @proxy_to_app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; # we don't want nginx trying to do something clever with # redirects, we set the Host: header above already. proxy_redirect off; proxy_pass http://app_server; } error_page 500 502 503 504 /500.html; location = /500.html { root /path/to/app/current/public; } }