본문 바로가기

# Development/DevOps

[Nginx] ubuntu 환경에서 Flask 배포하기 (Github, uWSGI, Socket)

ubuntu 환경에서 Flask 배포하기 (Github, uWSGI, Socket)

사전준비

패키지 매니징 툴 apt(Advance Packging Tools) 업데이트

$ sudo apt update

 

Git에서 소스코드 다운로드

1. Git 설치

$ sudo apt install git

2. Git 초기화

프로젝트를 시작하고 소스 코드를 Git으로 관리하고자 한다면 먼저 git init으로 저장소를 초기화 해야 한다. 저장소로 사용하고자 하는 디렉터리로 이동한 다음 git init을 실행한다.

$ git init

 

3. 소스코드 주소 복사

GIhub 홈페이지에서 가져올 프로젝트 주소 복사 (프로젝트 화면 > Code > Code > Clone > HTTPS)

4. git clone

$ git clone <복사한 소스코드 HTTPS 주소>

5. 복사된 소스코드  폴더로 이동

$ cd myproject

 

Flask 배포를 위해 필요한 패키지 다운로드

1. python 설치

 ~/myproject/$ sudo apt install python3-pip python3-dev python3-setuptools

2. ubuntu 빌드를 위한 패키지 설치

 ~/myproject/$ sudo apt install build-essential libssl-dev libffi-dev

 

Python 가상환경(Virtual Environment) 설정

1. venv 파이썬 패키지 다운로드

 ~/myproject/$ sudo apt install python3-venv

2. Flask 어플리케이션 위치에 'myproject_env' 가상환경 생성

: ~/myproject/$ python3 -m venv myproject_env

3. 가상환경 실행

: ~/myproject/$ source myproject_env/bin/activate

 

가상환경 실행 이후에는 앞에 (myproject_env)가 생성된다.

(myproject_env)user@host:~/myproject$

 

Flask 어플리케이션 설정

1. wheel 설치

WHL(Wheel) 파일은 Python의 휠 형식으로 저장된 배포 패키지 파일이다. pip 인스턴스에 wheel을 설치하여 패키지가 wheel 아카이브 파일이 없어도 설치될 수 있도록한다. 

(myproject_env)user@host:~/myproject$ pip install wheel

2. Flask에 사용된 패키지 다운로드

아래의 reqirements.txt는 로컬에서 pip freeze > requirements.txt 로 패키지 리스트 파일을 생성한다. 

(myproject_env)user@host:~/myproject$ pip install -r requirements.txt

3. uWSGI 설치

(myproject_env)user@host:~/myproject$ pip install uwsgi

 

Flask 어플리케이션 테스트

1. 어플리케이션 테스트를 위해 포트 5000에 대한 액세스 허용 

(myproject_env)user@host:~/myproject$ sudo ufw allow 5000

2. app = Flask(__name__) 정의가 포함된 파일 실행

1) 파일로 구동하는 경우

(myproject_env)user@host:~/myproject$ python myproject.py

[myproject.py]

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:pink'>Hellow World</h1>"

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

 

2) 모듈로 구동하는 경우

모듈의 __init__.py에 app = Flask(__name__) 가 정의된다. 

 

[Project Sturcture]

.
├── myproject
    ├── __init__.py
    ├── function1.py
    └── function2.py
└── run.py

이 경우에는 모듈을 run 하는 run.py 파일을 별도로 만들고, run.py를 실행한다.

(myproject_env)user@host:~/myproject$ python run.py

[run.py 예시]

# uwsg.py
from myproject import app

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

 

3. 테스트 실행 결과 확인

[콘솔 Output]

# Output
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Serving Flask app 'myproject'
 * Debug mode: off
 * Running on all addresses (0.0.0.0)
   WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://127.0.0.1:5000
 * Running on http://0.0.0.0:5000 (Press CTRL+C to quit)

서버 아이피를  포트 5000으로 접근하면 다음과 같은 화면을 확인 할 수 있다.

http://your_server_ip:5000

 

uWSGI 설정

1. WSGI 진입점(Entry Point) 생성

모듈로 Flask를 구동하는 경우 run.py가 Entry Point가 된다.

from myproject import app

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

2. WSGI 테스트하기

(env) uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

서버 아이피를  포트 5000으로 접근하면 다음과 같은 화면을 확인 할 수 있다.

http://your_server_ip:5000

 

3. uWSGI 구성 파일 생성

:~/myproject$ sudo nano myproject.ini
[uwsgi]
module = run:app  # run.py에서 app으로 정의된 항목이 모듈

master = true  # master 모드에서 시작
processes = 5  # request를 처리하기 위해 작동할 프로세스 수

socket = myproject.sock  # uWSGI와 웹 서버(예: Nginx) 간의 통신을 위한 소켓 파일의 경로
chmod-socket = 660 # 소켓 파일에 대한 퍼미션을 설정
vacuum = true # uWSGI 종료 시 생성된 소켓 파일을 자동으로 삭제하는 옵션

die-on-term = true

logger = file:/var/log/uwsgi/myproject.log  # 로그 설정
log-4xx = true  # 4xx 에러 로깅
log-5xx = true  # 5xx 에러 로깅


env = FLASK_ENV=development  # 환경변수 설정

 

systemd 서비스 등록(unit file 생성)

서버에 서비스를 등록하여 ubuntu 부팅시 uWSGI를 자동으로 시작하고, Falsk 어플리케이션을 서빙하도록 한다.

$ sudo nano /etc/systemd/system/myproject.service
[Unit] # 서비스의 전반적인 설정
Description = uWSGI instance to serve myproject # 서비스의 설명을 지정
After = network.target # 서비스가 network.target (네트워크 서비스) 이후에 시작되도록 설정

[Service]
User = ubuntu # 서비스를 실행할 사용자 계정을 지정
Group = www-data # 서비스를 실행할 때 사용할 그룹 지정
WrokingDirectory=/home/ubuntu/myproject # 서비스가 실행될 작업 디렉토리

# 서비스가 실행될 환경 변수 설정. 여기서는 가상 환경의 bin 디렉토리를 PATH에 추가
Environment="PATH=/home/ubuntu/myproject/myproject_env/bin"
# 서비스가 시작될 때 실행될 명령 지정
ExecStart=/home/ubuntu/myproject/myproject_env/bin/uwsgi --ini myproject.ini

[Install] 
WantedBy=multi-user.target

우분투에서는 기본적으로 Nginx의 www-data 사용자가 홈 디렉토리의 파일을 읽을 수 없으므로 chgrp 명령어를 사용하여 홈 디렉토리와 관련된 그룹을 변경한다.

$ sudo chgrp www-data /home/ubuntu

 

uWSGI 시작

1. uWSGI 시작

:~/myproject$ sudo systemctl start myproject
:~/myproject$ sudo systemctl enable myproject

2. uWSGI 재시작

:~/myproject$ sudo systemctl restart myproject

3. uWSGI 상태 확인

:~/myproject$ sudo systemctl status myproject

 

Nginx 프록시 구성

Nginx를 프록시로 구성하려면,  Nginx 설정파일에서 새로운 서버 블록을 생성해야 한다.

$ sudo nano /etc/nginx/sites-available/myproject

아래와 같이 서버 블록을 설정한다. 해당 서버 블록은 Nginx가 포트 80에서 요청을 수신해서 uwsgi_pass 경로의 소켓 파일로 요청을 전달하고, 서버의 도메인 이름에 대한 요청에 해당 블록을 사용하도록 정의한다.

server{
    listen 80;
    server_name your_domain;
    
    location / {
    	include uwsgi_params;
        uwsgi_pass unix:/home/ubuntu/myproject/myproject.sock;
    }
}

방금 만든 Nginx 서버 블록 구성을 활성화 하기 위해 해당 파일을 sites-enabled 디렉토리에 링크한다.

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

Nginx를 설치하면, 프로세스는 sites-available 디렉토리에 default라는 서버 블록 구성 파일을 자동으로 설정하고, 그 파일과 sites-enabled 디렉토리 사이에 심볼릭 링크를 만든다. 이 심볼릭 링크를 그대로 둘 경우, 기본 설정으로 인해 사이트가 로딩되지 않으므로 다음 명령어로 이 링크를 제거한다.

$ sudo unlink /etc/nginx/sites-enabled/default

 

Nginx 재시작

1. Nginx syntax error 확인

sudo nginx -t

2. Nginx 재시작

$ sudo systemctl restart nginx

 

어플리케이션 HTTPS 적용

서버로의 트래픽이 안전하게 유지되도록, 도메인에 대한 SSL 인증서를 얻어야 한다. Let's Encrypt에서 무료 인증서를 얻어서 적용 할 수 있다.

1. Certbot과 Certbot의 Ningx 플러그인 설치

$ sudo apt install certbot python3-certbot-nginx

2. Cerbot을 사용한 SSL 인증서 적용

$ sudo certbot --nginx -d your_domain -d www.your_domain

3. HTTP를 통한 접근 차단

$ sudo ufw delete allow 'Nginx HTTP'

 

 

🐬 참고

 

How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 22.04 | DigitalOcean

 

www.digitalocean.com

 

Ubuntu 16.04 Flask, django uwsgi 서비스 등록하기

Flask, django로 개발을 마친 후에 우분투 기반으로 서버를 가동하고 싶을 때, 사전 작업으로 기존에 쓰던 app.py 혹은 manage.py 를 사용하지 않고, 서버용 스크립트를 따로 만든다. 나는 보통 네이밍을

blog.ppuing.me