3 분 소요

앞서 uvicorn과 Gunicorn을 설치한 상태로 가정하겠습니다. FastAPI - 21 (Gunicorn)
Gunicorn을 설치 할 때와 비슷한 질문이 떠오르네요.
Nginx가 뭔가요? 왜 설치 해야 하나요? FastAPI는 Gunicorn으로 실행하는데 Nginx와 같이 실행 할 수 있나요? Gunicorn때와 동일하게 제가 설치한 내용을 간단히 정리 했습니다.

공식 사이트
https://www.nginx.com/
Nginx 공식 문서

Nginx?

Nginx는 강력한 웹 서버이자 리버스 프록시 서버로, 고성능과 효율적인 정적 콘텐츠 제공, 요청의 로드 밸런싱, SSL/TLS 암호화 등을 처리합니다.

왜 Gunicorn와 함께 사용하나요?

비동기적 처리를 하는 uviconr을 설치했고 안정성과 관리 기능을 활용하기 위해 Gunicorn을 설치했습니다. 그리고 또 강력한 웹서버인 Nginx를 설치해야 한다고 하는 군요.
제 경우는 Nginx의 리버스 프로시 기능과 https를 사용하기 위해 Nginx를 함께 사용하고 있습니다.

참고로 리버스 프로시란 외부의 요청을 Nginx가 받아 내부 네트워크의 특정 서버와 포트로 전달하는 것을 말합니다.

Nginx 설치(ubuntu 20.04)

apt를 통해 설치 합니다.

sudo apt install nginx

Nginx 설정

설정 파일을 생성합니다. 서버의 도메인을 ‘mycompany.co.kr’, A 레코드는 ‘fastapi’로 가정하겠습니다.외부에서 80 포트로 요청을 보내면 내부의 8000번 포트로 전달하도록 설정하겠습니다.

sudo vi /etc/nginx/sites-available/mycompany.co.kr

아래의 내용을 입력 합니다.

server {
        listen 80;
        server_name fastapi.mycompany.co.kr;

        location / {
                proxy_pass http://127.0.0.1:8000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host;                    
        }
}
  • listen 80;
    80번 포트(HTTP 기본 포트)에서 들어오는 요청을 수신하도록 설정합니다. http://fastapi.mycompany.co.kr 주소로 요청을 보낼 때 해당 요청을 Nginx가 받아들입니다.
  • server_name fastapi.mycompany.co.kr;
    Nginx가 처리할 서버의 도메인 이름을 지정합니다. 여기서는 fastapi.mycompany.co.kr이 해당 도메인입니다.
  • location / { … }
    location / 블록은 모든 URI 경로에 대한 요청(도메인 루트 및 그 하위의 모든 경로)을 처리하는 방법을 정의합니다.
  • proxy_pass http://127.0.0.1:8000;
    모든 들어오는 요청을 http://127.0.0.1:8000 (로컬 호스트의 8000번 포트)으로 전달하도록 설정합니다.

아래와 같이 심볼릭 링크를 생성합니다.

sudo ln -s /etc/nginx/sites-available/mycompany.co.kr /etc/nginx/sites-enabled/mycompany.co.kr 

Nginx실행

설정 파일을 생성하고 심볼릭 링크를 생성했으니 Nginx를 restart 합니다.

sudo systemctl restart nginx

변경 사항이 적용되었는지 확인합니다.

sudo nginx -t

Ngingx 명령어

  • Nginx 실행: sudo systemctl start nginx
  • Nginx 중지: sudo systemctl stop nginx
  • Nginx 재시작: sudo systemctl restart nginx
  • Nginx 상태 확인: sudo systemctl status nginx
  • Nginx 설정 파일 확인: sudo nginx -t
  • Nginx 설정 파일 재로드: sudo nginx -s reload
  • Nginx 설정 파일 위치: /etc/nginx/nginx.conf
  • Nginx 로그 파일 위치: /var/log/nginx/access.log, /var/log/nginx/error.log
  • Nginx 프로세스 확인: ps -ef | grep nginx

Nginx 테스트

먼저 FastAPI를 사용하여 간단한 API를 만들고 Gunicorn을 8000번 포트로 실행합니다. 8000번 포트는 외부에서 접근 할 수 없다고 가정하겠습니다. FastAPI - 21 (Gunicorn)

gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

웹 브라우저를 열고 http://fastapi.mycompany.co.kr:8000/로 접속하면 접속이 되지 않습니다.

80 포트로 접속 해 보겠습니다. Nginx가 실행되고 있지 않으면 start 또는 restart 합니다.

sudo systemctl start nginx
# sudo systemctl restart nginx

웹 브라우저를 열고 http://fastapi.mycompany.co.kr/로 접속하면 아래의 결과를 확인 할 수 있습니다.

{"message":"Hello World"}

80포트로 접속하였으나 내부의 8000번 포트로 실행한 Guniorcn으로 전달되어 처리되었습니다.

https 설정

Nginx를 사용하여 https를 설정하겠습니다.

Nginx 웹 서버에 대한 Certbot의 자동 설정을 가능하게 하는 플러그인을 설치합니다.

sudo apt install certbot python3-certbot-nginx

필요 시 방화벽을 열어줍니다.

sudo ufw allow 'Nginx Full' # HTTP(80)와 HTTPS(443) 모두 허용
sudo ufw delete allow 'Nginx HTTP' # 기존의 HTTP 허용 설정 제거

Certbot을 사용하여 SSL 인증서를 발급합니다.

sudo certbot --nginx -d mycompany.co.kr

이메일 주소 입력 외 몇 가지 선택 사항이 나오면서 진행이 완료 됩니다.

https 테스트

sudo nginx -t
sudo systemctl restart nginx

웹 브라우저를 열고 https://fastapi.mycompany.co.kr/로 접속하면 아래의 결과를 확인 할 수 있습니다.

{"message":"Hello World"}

외부에서 80 포트로 https 요청을 하면 내부의 8000(방화벽이 열지 있지 않은)번 포트로 전달되어 처리되었습니다.

URL에 따른 내부 포트 분기

URL(호스트)에 따라 내부 포트를 분기하여 처리하도록 설정하겠습니다.

예를 들어 특정 서버가 ‘mycompany.co.kr’와 매핑 되어 있습니다. ‘fastapi.mycompany.co.kr’로 요청하면 서버 내부의 8000 포트로 전달되고 ‘flask.mycompany.co.kr’로 요청하면 서버 내부의 9000 포트로 전달되게 구현하고 싶습니다.
서버의 8000번과 9000번 포트는 서비스가 실행 중이며 외부에서 접근 할 수 없다고 가정하겠습니다.

Nginx의 설정 파일을 생성

sudo vi /etc/nginx/sites-available/mycompany.co.kr

각 호스트에 따른 서버 블록을 각각 설정합니다.

# 첫 번째 서버 블록: fastapi.mycompany.co.kr을 포트 8000으로 라우팅
server {
    listen 80;
    server_name fastapi.mycompany.co.kr;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;                            
    }
}

# 두 번째 서버 블록: flask.mycompany.co.kr을 포트 9000으로 라우팅
server {
    listen 80;
    server_name flask.mycompany.co.kr;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;          
    }
}

vi를 저장하고 종료합니다.

Nginx 심볼릭 링크 생성

sudo ln -s /etc/nginx/sites-available/mycompany.co.kr /etc/nginx/sites-enabled/mycompany.co.kr

기존 파일이 존재하면 삭제하고 생성합니다.

Nginx 재시작

sudo systemctl restart nginx
sudo nginx -t

인증서 발급

sudo certbot --nginx -d fastapi.mycompany.co.kr -d flask.mycompany.co.kr

2개 호스트에 대한 인증서를 발급 받습니다.

Nginx를 재시작 합니다.

sudo systemctl restart nginx
sudo nginx -t

테스트

https://fastapi.mycompany.co.kr/로 접속 => 내부 8000번 포트의 서비스가 실행 https://flask.mycompany.co.kr/로 접속 => 내부 9000번 포트의 서비스가 실행


해시태그: #fastapi #uvicorn #Gunicorn #Nginx #SSL #https

댓글남기기