[python][인터넷] Flask 또는 Django를 Production 서버로 배포(Deploy)하기

Photo by Hitesh Choudhary on Unsplash

파이썬 웹 애플리케이션을 Production 서버로 배포하는 것은 다소 까다로운 편이다.

그 이유는 WSGI가 필요하기 때문인데 이 시간에는 어떻게 파이썬 웹 애플리케이션을 서버에 올리는지 알아보도록 하겠다.

참고로 WSGI에 대해서 잘 모르시는 분은 예전에 서버에 대해서 정리해둔 글이 있으니 참고 바란다.

 

 

개괄

우선 파이썬 웹 애플리케이션이 구동되는 전체적인 그림을 먼저 알아보도록 하자.

우리는 WSGI 서버 중 Gunicorn(구니콘)을 이용하여 서버를 구동할것이다.

(Gunicorn의 경우 Unix 또는 Linux 환경에서만 구동되므로 참고 바란다. 해당 글은 Ubuntu기준으로 설명 한다.)

Gunicorn만으로도 서버 구동이 가능하나 단독으로 사용할시 아래와 같은 문제점이 있다.

  • DDos등 외부 공격 취약
  • HTTPS 처리 불가
  • Static 파일의 전송 효율성
  • 다수의 연결을 효과적으로 처리 불가

이를 해결하기 위해 보통 Nginx를 이용하게 되는데 나중에 살펴보겠지만 프록시로 Gunicorn에게 요청을 넘겨주게 된다.

각설하고 이제 구체적으로 이를 어떻게 설정하는지 살펴보도록 하자.

Gunicorn 설정

1. 설치

먼저 파이썬 웹 애플리케이션을 구동하기 위해 Gunicorn의 설치가 필요하다.

아래 명령어를 통해 프로젝트에 Gunicorn을 설치하도록 한다.

pip install gunicorn

만약 가상환경을 이용한다면 가상환경 안에서 설치해줘야 한다.

2. Gunicorn 테스트

아래 명령어를 통해 잘 구동이 되는지 확인해본다.

gunicorn --bind 0.0.0.0:8000 [Project file path]:app

여기서 [Project file path] 는 시작할 파일의 경로를 적어준다.

경로는 마침표(.)으로 구분해주며 예를들어 src/index.py 를 구동한다고 했을 때 최종적인 명령어는 아래와 같다.

gunicorn --bind 0.0.0.0:8000 src.index:app

이제 0.0.0.0:8000 에 접속하여 이상이 없는지 확인한다.

3. Gunicorn 서비스 등록하기

Gunicorn을 일일히 명령어로 실행되기 보다. 안정적으로 서버가 재시작 되더라도 구동되기 위해 서비스 등록이 필요하다.

시스템에 gunicorn을 등록하기 위해 우선 아래 경로로 편집기를 이용하여 열어준다.

$ vim /etc/systemd/system/gunicorn.service

이후 아래와 같은 내용을 입력해준다.

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=[유저 이름]
Group=[유저 그룹]
WorkingDirectory=[파이썬 웹 애플리케이션 프로젝트 경로]
ExecStart=[Gunicorn 설치 경로] --workers 3 --bind 0.0.0.0:8000 [프로젝트 경로]:app

[Install]
WantedBy=multi-user.target

[변수 이름] 에 대한 설명은 아래와 같다.

  • [유저 이름]

: Linux환경의 유저 이름 아래 명령어를 통해 확인 해 볼 수 있다.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

$ whoami
  • [유저 그룹]

위의 유저 이름이 속한 그룹 아래 명령어를 통해 확인 가능하다.

$ groups [사용자명]
  • [Gunicorn 설치 경로]

Gunicorn이 설치된 경로 만약 가상환경을 통해 설치됐다면 가상환경의 설치 경로를 적어준다.

위의 내용을 토대로 작성된 최종적인 파일은 아래와 비슷한 모습이다.

[Unit]
Description=gunicorn daemon
After=network.target[Service]
User=root
Group=root 
WorkingDirectory=/root/video_cron
ExecStart=/root/video_cron/venv/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 src.index:app[Install]
WantedBy=multi-user.target

여기서 로그 작업을 추가하거나 코드가 변경 되었을때 Gunicorn이 자동으로 재시작 되어 반영되도록 할 수 있는데 ExecStart에 몇가지 옵션을 추가해주면 된다.

...
ExecStart=/root/video_cron/venv/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 src.index:app --reload --error-logfile /root/logs/debug.log --access-logfile /root/logs/access.log --capture-output --log-level debug
...

위의 /root/logs/debug.log, /root/logs/access.log 파일이 존재 해야 에러가 발생하지 않으므로 없다면 빈파일을 만들어 준다.

옵션에 대한 설명 또는 다른 추가적이 기능이 필요하다면 아래 링크를 참고 바란다.

이제 모두 작성을 마쳤다면 아래 명령어를 통해 Gunicorn의 서비스를 등록해준다.

$ sudo systemctl start gunicorn # Gunicorn 서비스 시작
$ sudo systemctl enable gunicorn # 시스템 재시작시 Gunicorn 자동 시작
$ sudo systemctl status gunicorn.service # Gunicorn 서비스 상태 확인

active (running)이 되었다면 정상적으로 실행된 것이다.

Nginx 설정

1. 설치

아래 명령어를 통해 우선 Nginx를 시스템에 설치 해주도록 하자.

$ sudo apt-get update
$ sudo apt-get install nginx

2. 설정

Nginx의 설정을 바꿔야 하는데 /etc/nginx/sites-enabled/ 의 하위에 설정 파일이 위치한다 기본적으로 default 파일이 있는데 이를 삭제하고 이름을 바꿔 새로 작성해주거나 그냥 default 파일을 수정해도 무관하다.

설정 파일을 우선 관리자 권한으로 열어준다.

$ sudo vim /etc/nginx/sites-enabled/[설정파일이름]

해당 파일에 아래와 같은 내용을 작성한다.

server {
    listen 80;
    server_name [Public IP주소];

    charset utf-8;

    location / {
        include proxy_params;
        proxy_pass http://[Public IP주소]:8000;

    }
}

[Public IP주소] 대신에 도메인이 있다면 이를 적어줘도 무방하다.

3. Nginx 재시작 하기

설정 파일이 반영되기 위해선 Nginx의 재시작이 필요하다.

$ sudo service nginx restart

재시작 후 마찬가지로 정상적으로 실행 되었는지 아래 명령어로 확인해보자.

$ sudo service nginx status

서버 접속 테스트

지금까지 왔다면 Production 서버의 설정을 모두 완료한 것이다.

이제 설정한 Public IP (또는 도메인)으로 접속해서 정상적으로 접속되는지 확인해보자.

Nginx에서 80포트를 설정 했으므로 브라우저에 Public IP (또는 도메인)만 주소 창에 입력하면 접속 가능하다.

정리

요청은 아래와 같은 순서로 전달된다.

  1. 브라우저에서 주소에 아이피 또는 도메인을 입력시 Nginx로 요청이 전달된다.

2. Nginx는 프록시로 Gunicorn으로 요청을 전달한다.

3. Gunicorn은 전달 받은 요청을 Flask 또는 Django에 전달한다.

응답은 이의 역순으로 이뤄어지며 다시 한번 처음 봤던 그림을 보고 이해 해보자.

[출처] https://jay-flow.medium.com/flask-%EB%98%90%EB%8A%94-django%EB%A5%BC-production-%EC%84%9C%EB%B2%84%EB%A1%9C-%EB%B0%B0%ED%8F%AC-deploy-%ED%95%98%EA%B8%B0-1abadb0b941a
본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
431 [Python 인터넷] django REST framework로 간단한 api 만들기 file 졸리운_곰 2023.03.08 10
430 [Python 인터넷] Quickstart - Django REST framework 졸리운_곰 2023.03.08 21
429 [python][자료구조] [MongoDB] Document Query(조회) – find() 메소드 졸리운_곰 2023.03.08 7
428 [python][자료구조] Python(flask)으로 mongoDB 제어하기 – pymongo file 졸리운_곰 2023.03.08 30
427 [python, tkinter] [python/GUI] tkinter 로 GUI 만들기(기초예제, 단위 변환기 만들기) file 졸리운_곰 2023.03.07 17
426 [Python 인터넷] 세상에서 가장 간단한 Airflow 튜토리얼 file 졸리운_곰 2023.03.05 11
425 [Python 인터넷] Flask 또는 Django를 Production 서버로 배포(Deploy)하기 file 졸리운_곰 2023.03.03 10
424 [Python 인터넷] django 웹사이트 배포를 하며 겪은 시행착오 졸리운_곰 2023.03.03 3
423 [Python 인터넷] Windows에서 Django와 Apache 연동하기 졸리운_곰 2023.03.02 28
422 [python][자료구조] django sqlite3 MySQL로 전환하기 file 졸리운_곰 2023.03.02 6
421 [python][자료구조] django에서 db.sqlite3 데이터를 mysql로 옮기기 졸리운_곰 2023.03.02 5
420 [python][자료구조] Python - JSON 파일 읽고 쓰는 방법 졸리운_곰 2023.02.04 19
419 [python][자료구조] [인코딩] 유니코드 인코딩 처리 (특히 json 입출력 시) 졸리운_곰 2023.02.04 8
418 [Python 인터넷] 구글로 공부하는 파이썬 - 부록 (IIS, Apache 로 Flask 돌리기) file 졸리운_곰 2023.01.26 20
417 [python 인터넷] Flask로 REST API 구현하기 - 3. JWT로 사용자 인증하기 졸리운_곰 2023.01.26 8
416 [python 인터넷] Flask로 REST API 구현하기 - 2. 파일 분리, 문서화 졸리운_곰 2023.01.26 8
415 [python 인터넷] Flask로 REST API 구현하기 - 1. Flask-RESTX file 졸리운_곰 2023.01.26 11
414 [python 인터넷] 초간단 API서버 만들기 - 1부 (Python + Flask + Apache) file 졸리운_곰 2023.01.24 11
» [python][인터넷] Flask 또는 Django를 Production 서버로 배포(Deploy)하기 file 졸리운_곰 2023.01.17 9
412 [python][flask] (flask) windows에서 flask와 apache 연동 file 졸리운_곰 2023.01.17 7
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED