웹사이트 검색

Ubuntu 16.04에서 uWSGI 및 Nginx로 Flask 애플리케이션을 제공하는 방법


소개

이 가이드에서는 Ubuntu 16.04에서 Flask 마이크로 프레임워크를 사용하여 간단한 Python 애플리케이션을 설정합니다. 이 기사의 대부분은 uWSGI 애플리케이션 서버를 설정하여 애플리케이션을 시작하고 Nginx가 프런트 엔드 리버스 프록시로 작동하도록 설정하는 방법에 관한 것입니다.

전제 조건

이 가이드를 시작하기 전에 서버에 루트가 아닌 사용자가 구성되어 있어야 합니다. 이 사용자는 관리 기능을 수행할 수 있도록 sudo 권한이 있어야 합니다. 설정 방법을 알아보려면 초기 서버 설정 가이드를 따르세요.

uWSGI, 애플리케이션 서버 및 WSGI 사양에 대한 자세한 내용은 이 가이드의 링크된 섹션을 참조하십시오. 이러한 개념을 이해하면 이 가이드를 더 쉽게 따라갈 수 있습니다.

계속할 준비가 되면 계속 읽으십시오.

Ubuntu 리포지토리에서 구성 요소 설치

첫 번째 단계는 리포지토리에서 필요한 모든 부분을 설치하는 것입니다. Python 구성 요소를 설치하고 관리하기 위해 Python 패키지 관리자인 pip를 설치합니다. 또한 uWSGI를 빌드하는 데 필요한 Python 개발 파일을 얻고 Nginx도 지금 설치합니다.

로컬 패키지 인덱스를 업데이트한 다음 패키지를 설치해야 합니다. 필요한 패키지는 프로젝트에서 Python 2 또는 Python 3을 사용하는지 여부에 따라 다릅니다.

Python 2를 사용하는 경우 다음을 입력합니다.

  1. sudo apt-get update
  2. sudo apt-get install python-pip python-dev nginx

대신 Python 3을 사용하는 경우 다음을 입력합니다.

  1. sudo apt-get update
  2. sudo apt-get install python3-pip python3-dev nginx

Python 가상 환경 만들기

다음으로 Flask 애플리케이션을 시스템의 다른 Python 파일과 격리하기 위해 가상 환경을 설정합니다.

pip를 사용하여 virtualenv 패키지를 설치하여 시작하십시오.

Python 2를 사용하는 경우 다음을 입력합니다.

  1. sudo pip install virtualenv

Python 3을 사용하는 경우 다음을 입력합니다.

  1. sudo pip3 install virtualenv

이제 Flask 프로젝트의 상위 디렉터리를 만들 수 있습니다. 만든 후 디렉터리로 이동합니다.

  1. mkdir ~/myproject
  2. cd ~/myproject

다음을 입력하여 Flask 프로젝트의 Python 요구 사항을 저장할 가상 환경을 만들 수 있습니다.

  1. virtualenv myprojectenv

이렇게 하면 프로젝트 디렉터리 내의 myprojectenv라는 디렉터리에 Pythonpip의 로컬 복사본이 설치됩니다.

가상 환경에 애플리케이션을 설치하기 전에 활성화해야 합니다. 다음을 입력하면 됩니다.

  1. source myprojectenv/bin/activate

이제 가상 환경 내에서 작업 중임을 나타내도록 프롬프트가 변경됩니다. 다음과 같이 표시됩니다. (myprojectenv)user@host:~/myproject$.

Flask 애플리케이션 설정

이제 가상 환경에 있으므로 Flask 및 uWSGI를 설치하고 애플리케이션 설계를 시작할 수 있습니다.

Flask 및 uWSGI 설치

pip의 로컬 인스턴스를 사용하여 Flask 및 uWSGI를 설치할 수 있습니다. 다음 명령을 입력하여 이 두 구성 요소를 가져옵니다.

사용 중인 Python 버전에 관계없이 가상 환경이 활성화되면 pip 명령(pip3 아님)을 사용해야 합니다.

  1. pip install uwsgi flask

샘플 앱 만들기

이제 Flask를 사용할 수 있으므로 간단한 애플리케이션을 만들 수 있습니다. Flask는 마이크로 프레임워크입니다. 완전한 기능을 갖춘 프레임워크가 제공할 수 있는 많은 도구를 포함하지 않으며 주로 웹 애플리케이션 초기화를 지원하기 위해 프로젝트로 가져올 수 있는 모듈로 존재합니다.

애플리케이션이 더 복잡할 수 있지만 myproject.py라고 하는 단일 파일에 Flask 앱을 만들 것입니다.

  1. nano ~/myproject/myproject.py

이 파일 내에 애플리케이션 코드를 배치합니다. 기본적으로 Flask를 가져와서 Flask 개체를 인스턴스화해야 합니다. 이를 사용하여 특정 경로가 요청될 때 실행되어야 하는 기능을 정의할 수 있습니다.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

이것은 기본적으로 루트 도메인에 액세스할 때 표시할 콘텐츠를 정의합니다. 완료되면 파일을 저장하고 닫습니다.

초기 서버 설정 가이드를 따랐다면 UFW 방화벽을 활성화해야 합니다. 애플리케이션을 테스트하려면 포트 5000에 대한 액세스를 허용해야 합니다.

다음을 입력하여 포트 5000을 엽니다.

  1. sudo ufw allow 5000

이제 다음을 입력하여 Flask 앱을 테스트할 수 있습니다.

  1. python myproject.py

웹 브라우저에서 서버의 도메인 이름 또는 IP 주소 다음에 :5000을 방문하십시오.

http://server_domain_or_IP:5000

다음과 같은 내용이 표시되어야 합니다.

완료되면 터미널 창에서 CTRL-C를 몇 번 눌러 Flask 개발 서버를 중지합니다.

WSGI 진입점 생성

다음으로 애플리케이션의 진입점 역할을 할 파일을 생성합니다. 이는 uWSGI 서버에 애플리케이션과 상호 작용하는 방법을 알려줍니다.

wsgi.py 파일을 호출합니다.

  1. nano ~/myproject/wsgi.py

파일은 매우 간단합니다. 애플리케이션에서 Flask 인스턴스를 가져온 다음 실행할 수 있습니다.

from myproject import app

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

완료되면 파일을 저장하고 닫습니다.

uWSGI 구성

이제 애플리케이션이 작성되었으며 진입점이 설정되었습니다. 이제 uWSGI로 넘어갈 수 있습니다.

uWSGI 서빙 테스트

우리가 할 첫 번째 일은 uWSGI가 애플리케이션을 제공할 수 있는지 테스트하는 것입니다.

단순히 진입점의 이름을 전달하여 이를 수행할 수 있습니다. 이것은 모듈의 이름(평소와 같이 .py 확장자 제외)과 애플리케이션 내에서 호출 가능한 이름으로 구성됩니다. 우리의 경우 이것은 wsgi:app입니다.

또한 공개적으로 사용 가능한 인터페이스에서 시작되도록 소켓을 지정하고 uwsgi 바이너리 프로토콜 대신 HTTP를 사용하도록 프로토콜을 지정합니다. 이전에 연 것과 동일한 포트 번호를 사용합니다.

  1. uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

웹 브라우저에서 끝에 :5000이 추가된 서버의 도메인 이름 또는 IP 주소를 다시 방문하십시오.

http://server_domain_or_IP:5000

애플리케이션의 출력이 다시 표시되어야 합니다.

제대로 작동하는지 확인했으면 터미널 창에서 CTRL-C를 누릅니다.

이제 가상 환경이 완성되었으므로 비활성화할 수 있습니다.

  1. deactivate

모든 Python 명령은 이제 시스템의 Python 환경을 다시 사용합니다.

uWSGI 구성 파일 생성

우리는 uWSGI가 우리의 애플리케이션을 제공할 수 있는지 테스트했지만 장기간 사용을 위해 더 강력한 것을 원합니다. 원하는 옵션으로 uWSGI 구성 파일을 만들 수 있습니다.

프로젝트 디렉토리에 넣고 myproject.ini라고 부르겠습니다.

  1. nano ~/myproject/myproject.ini

내부에서 [uwsgi] 헤더로 시작하여 uWSGI가 설정을 적용하는 것을 알 수 있도록 합니다. 확장자를 제외한 wsgi.py 파일을 참조하여 모듈을 지정하고 파일 내의 호출 가능 항목을 "app\이라고 합니다.

[uwsgi]
module = wsgi:app

다음으로 마스터 모드에서 시작하고 실제 요청을 처리하기 위해 5개의 작업자 프로세스를 생성하도록 uWSGI에 지시합니다.

[uwsgi]
module = wsgi:app

master = true
processes = 5

테스트할 때 네트워크 포트에 uWSGI를 노출했습니다. 그러나 우리는 Nginx를 사용하여 실제 클라이언트 연결을 처리하고 요청을 uWSGI로 전달할 것입니다. 이러한 구성 요소는 동일한 컴퓨터에서 작동하므로 Unix 소켓이 더 안전하고 빠르기 때문에 선호됩니다. 소켓 myproject.sock을 호출하고 이 디렉토리에 배치합니다.

소켓에 대한 권한도 변경해야 합니다. 나중에 uWSGI 프로세스의 Nginx 그룹 소유권을 부여할 것이므로 소켓의 그룹 소유자가 정보를 읽고 쓸 수 있는지 확인해야 합니다. 또한 "vacuum\ 옵션을 추가하여 프로세스가 중지될 때 소켓을 정리합니다.

[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

마지막으로 해야 할 일은 die-on-term 옵션을 설정하는 것입니다. 이는 초기화 시스템과 uWSGI가 각 프로세스 신호의 의미에 대해 동일한 가정을 갖도록 하는 데 도움이 될 수 있습니다. 이를 설정하면 두 시스템 구성 요소가 정렬되어 예상되는 동작을 구현합니다.

[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

명령줄에서 했던 것처럼 프로토콜을 지정하지 않았다는 것을 눈치채셨을 것입니다. 기본적으로 uWSGI는 다른 서버와 통신하도록 설계된 빠른 바이너리 프로토콜인 uwsgi 프로토콜을 사용하여 말하기 때문입니다. Nginx는 기본적으로 이 프로토콜을 말할 수 있으므로 HTTP로 통신을 강제하는 것보다 이것을 사용하는 것이 좋습니다.

완료되면 파일을 저장하고 닫습니다.

시스템 단위 파일 생성

다음으로 처리해야 할 부분은 systemd 서비스 단위 파일입니다. systemd 단위 파일을 생성하면 Ubuntu의 초기화 시스템이 자동으로 uWSGI를 시작하고 서버가 부팅될 때마다 Flask 애플리케이션을 제공할 수 있습니다.

시작하려면 /etc/systemd/system 디렉토리 내에 .service로 끝나는 단위 파일을 만듭니다.

  1. sudo nano /etc/systemd/system/myproject.service

내부에서는 메타데이터 및 종속성을 지정하는 데 사용되는 [Unit] 섹션부터 시작합니다. 여기에 서비스에 대한 설명을 입력하고 네트워킹 대상에 도달한 후에만 서비스를 시작하도록 init 시스템에 알립니다.

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

다음으로 [Service] 섹션을 엽니다. 프로세스를 실행할 사용자와 그룹을 지정합니다. 모든 관련 파일을 소유하고 있으므로 프로세스의 일반 사용자 계정 소유권을 부여합니다. Nginx가 uWSGI 프로세스와 쉽게 통신할 수 있도록 그룹 소유권을 www-data 그룹에 부여합니다.

그런 다음 작업 디렉토리를 매핑하고 PATH 환경 변수를 설정하여 init 시스템이 프로세스의 실행 파일이 있는 위치(가상 환경 내)를 알 수 있도록 합니다. 그런 다음 서비스를 시작하라는 명령을 지정합니다. Systemd는 가상 환경에 설치된 uWSGI 실행 파일의 전체 경로를 제공해야 합니다. 프로젝트 디렉터리에 생성한 .ini 구성 파일의 이름을 전달합니다.

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

마지막으로 [Install] 섹션을 추가합니다. 이것은 우리가 부팅시 시작할 수 있게 한다면 이 서비스를 무엇에 연결할지 systemd에게 알려줄 것입니다. 일반 다중 사용자 시스템이 실행 중일 때 이 서비스가 시작되기를 원합니다.

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

이것으로 systemd 서비스 파일이 완성되었습니다. 지금 저장하고 닫습니다.

이제 생성한 uWSGI 서비스를 시작하고 부팅 시 시작되도록 활성화할 수 있습니다.

  1. sudo systemctl start myproject
  2. sudo systemctl enable myproject

프록시 요청에 대한 Nginx 구성

이제 uWSGI 애플리케이션 서버가 가동되어 프로젝트 디렉토리의 소켓 파일에 대한 요청을 기다리고 있어야 합니다. uwsgi 프로토콜을 사용하여 해당 소켓에 웹 요청을 전달하도록 Nginx를 구성해야 합니다.

Nginx의 sites-available 디렉터리에 새 서버 블록 구성 파일을 생성하여 시작합니다. 가이드의 나머지 부분과 일치하도록 이 myproject를 호출하기만 하면 됩니다.

  1. sudo nano /etc/nginx/sites-available/myproject

서버 블록을 열고 기본 포트 80에서 수신하도록 Nginx에 지시합니다. 또한 서버의 도메인 이름 또는 IP 주소 요청에 이 블록을 사용하도록 지시해야 합니다.

server {
    listen 80;
    server_name server_domain_or_IP;
}

우리가 추가해야 할 유일한 다른 것은 모든 요청과 일치하는 위치 블록입니다. 이 블록 내에서 설정해야 하는 일반적인 uWSGI 매개변수를 지정하는 uwsgi_params 파일을 포함합니다. 그런 다음 uwsgi_pass 지시문을 사용하여 정의한 소켓에 요청을 전달합니다.

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/sammy/myproject/myproject.sock;
    }
}

이것이 실제로 애플리케이션을 제공하는 데 필요한 전부입니다. 완료되면 파일을 저장하고 닫습니다.

방금 만든 Nginx 서버 블록 구성을 활성화하려면 파일을 sites-enabled 디렉터리에 연결합니다.

  1. sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

해당 디렉터리에 있는 파일을 사용하여 다음을 입력하여 구문 오류를 테스트할 수 있습니다.

  1. sudo nginx -t

이것이 문제를 나타내지 않고 반환되면 Nginx 프로세스를 다시 시작하여 새 구성을 읽을 수 있습니다.

  1. sudo systemctl restart nginx

마지막으로 해야 할 일은 방화벽을 다시 조정하는 것입니다. 더 이상 포트 5000을 통한 액세스가 필요하지 않으므로 해당 규칙을 제거할 수 있습니다. 그런 다음 Nginx 서버에 대한 액세스를 허용할 수 있습니다.

  1. sudo ufw delete allow 5000
  2. sudo ufw allow 'Nginx Full'

이제 웹 브라우저에서 서버의 도메인 이름 또는 IP 주소로 이동할 수 있습니다.

http://server_domain_or_IP

애플리케이션 출력이 표시되어야 합니다.

Nginx를 구성한 후 다음 단계는 SSL/TLS를 사용하여 서버에 대한 트래픽을 보호하는 것입니다. 이것이 없으면 암호를 포함한 모든 정보가 일반 텍스트로 네트워크를 통해 전송되기 때문에 이것은 중요합니다.

트래픽을 보호하기 위해 SSL 인증서를 얻는 가장 쉬운 방법은 Let’s Encrypt를 사용하는 것입니다. Ubuntu 16.04에서 Nginx로 Let’s Encrypt를 설정하려면 이 가이드를 따르십시오.

결론

이 가이드에서는 Python 가상 환경 내에 간단한 Flask 애플리케이션을 만들었습니다. WSGI 지원 애플리케이션 서버가 인터페이스할 수 있도록 WSGI 진입점을 생성한 다음 이 기능을 제공하도록 uWSGI 앱 서버를 구성했습니다. 그런 다음 시스템 서비스 파일을 생성하여 부팅 시 애플리케이션 서버를 자동으로 시작했습니다. 웹 클라이언트 트래픽을 애플리케이션 서버로 전달하여 외부 요청을 릴레이하는 Nginx 서버 블록을 생성했습니다.

Flask는 매우 단순하지만 매우 유연한 프레임워크로서 구조와 디자인에 대해 너무 제한적이지 않으면서 애플리케이션에 기능을 제공합니다. 이 가이드에 설명된 일반 스택을 사용하여 설계한 플라스크 애플리케이션을 제공할 수 있습니다.