이번 장에서는 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
BASH


venv 를 활성화합니다.

$ . venv/bin/activate
BASH


이제 Python Flask 를 사용자 모드로 설치합니다.

$ pip install Flask --user
BASH

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"
PY


이제 python flask 에 내장된 기본 웹 서버를 실행해서 테스트 해봅니다.

FLASK_APP=hello flask run --host 127.0.0.1 --port 8888
BASH

브라우저에서 연결한 후에 / 와 /hello 라우팅에 연결해서 정상 작동 여부를 확인합니다.


방화벽때문에 연결이 안 될 경우 방화벽을 여는 것보다는 서버에서 curl 등 커맨드에서 연결 확인하는 게 좋습니다.

$ curl -v localhost:8888/hello
BASH


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
BASH


현재 폴더에 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])
PY


이제 gunicorn 을 구동합니다.

gunicorn -w 1 myapp:app -b 127.0.0.1:8888
BASH


제대로 동작하는지 확인하기 위해 curl 로 요청해 봅니다.

curl -I 127.0.0.1:8888
BASH


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;
    }
  }
CODE



Ref