FastAPI를 이용한 TDD 개발 - 7

2024. 3. 19. 21:43·프로그래밍 언어/파이썬

 

Heroku 서버에 배포를 해보겠습니다.

 

Gunicorn

프로덕션급 WSGI 서버인 Gunicorn을 사용하려면 먼저 requirements.txt 파일에 라이브러리와 버전을 명시합니다. 

gunicorn==21.0.1

 

Gunicorn과 Uvicorn을 함께 사용하는 이유는 동시성과 병렬성의 장점을 모두 활용하기 위해서입니다.
Gunicorn은 여러 Uvicorn 프로세스를 동시에 관리하여 이를 달성합니다.

 

Dockerfile.prod 라는 Dockerfile를 새로게 작성해줍니다. 

# pull official base image
FROM python:3.12.1-slim-bookworm

# create directory for the app user
RUN mkdir -p /home/app

# create the app user
RUN addgroup --system app && adduser --system --group app

# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV ENVIRONMENT prod
ENV TESTING 0

# install system dependencies
RUN apt-get update \
  && apt-get -y install netcat-traditional gcc postgresql \
  && apt-get clean

# install python dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
RUN pip install "uvicorn[standard]==0.26.0"

# add app
COPY . .

# chown all the files to the app user
RUN chown -R app:app $APP_HOME

# change to the app user
USER app

# run gunicorn
CMD gunicorn --bind 0.0.0.0:$PORT app.main:app -k uvicorn.workers.UvicornWorker

 

 

Gunicorn 실행을 위한 CMD 추가: Docker 컨테이너가 시작될 때 자동으로 실행될 명령을 정의합니다. 여기서는 Gunicorn을 Uvicorn worker class(-k uvicorn.workers.UvicornWorker)와 함께 실행하여 ASGI 애플리케이션을 호스팅하는 구성입니다. 이를 통해 비동기 Python 애플리케이션을 효율적으로 관리하고 실행할 수 있습니다.


새로운 환경 변수 구성: Dockerfile에는 ENVIRONMENT와 TESTING이라는 두 개의 환경 변수가 추가되었습니다. ENVIRONMENT 변수는 애플리케이션이 실행되는 환경(예: prod로 설정된 경우 운영 환경)을 지정하고, TESTING 변수는 애플리케이션이 테스트 모드에서 실행되고 있는지 여부를 나타내는 데 사용됩니다(0은 비활성화, 1은 활성화).

이러한 설정은 Docker 컨테이너 내에서 Python 웹 애플리케이션을 실행할 때 필요한 환경을 구축하고, Gunicorn을 사용하여 여러 Uvicorn 인스턴스를 관리함으로써 동시성과 병렬성을 효과적으로 활용할 수 있도록 합니다. Gunicorn은 여러 워커를 관리하여 부하 분산과 프로세스 관리를 담당하며, Uvicorn은 비동기 프로그래밍을 지원하는 가벼운 ASGI 서버로 각 워커에서 실행됩니다.

 

ENV ENVIRONMENT prod
ENV TESTING 0

 

위 문장에서는 Docker 컨테이너를 구성하면서 취한 두 가지 중요한 보안 및 호환성 조치를 설명하고 있습니다.

1. 비루트 사용자(non-root user) 생성 및 전환: Docker 컨테이너에서 실행되는 애플리케이션의 보안을 강화하기 위해, 루트 사용자가 아닌 비루트 사용자를 생성하고 이 사용자로 전환하는 작업을 진행합니다. 이는 Heroku와 같은 플랫폼에서 권장하는 보안 사례입니다. 루트 사용자로 애플리케이션을 실행할 경우, 애플리케이션이 노출될 수 있는 보안 위험이 증가하기 때문에, 비루트 사용자를 사용하여 이러한 위험을 줄이는 것입니다.

2. $PORT 환경 변수: Gunicorn 명령어에서 `$PORT` 환경 변수의 사용은 특히 중요합니다. 이 환경 변수는 Heroku와 같은 클라우드 플랫폼에서 애플리케이션이 반드시 듣고 있어야 하는 포트 번호를 지정합니다. 즉, Heroku는 동적으로 포트 번호를 할당하고, 이 할당된 포트 번호는 `$PORT` 환경 변수를 통해 애플리케이션에 제공됩니다. 따라서, 애플리케이션은 이 환경 변수를 통해 제공된 포트에서 리스닝해야 하며, Gunicorn 설정에서 이를 반영하기 위해 `--bind 0.0.0.0:$PORT` 옵션을 사용합니다.

이 두 조치는 보안을 강화하고, 클라우드 플랫폼에서의 애플리케이션 배포를 위한 호환성을 보장하는 데 중요합니다. 비루트 사용자로의 전환은 보안 리스크를 줄이는 한편, `$PORT` 환경 변수의 사용은 Heroku와 같은 클라우드 서비스에서 요구하는 동적 포트 할당을 지원하여, 애플리케이션이 문제 없이 서비스될 수 있도록 합니다.

Heroku

헤로쿠 계정에 가입한 다음 Heroku CLI를 설치합니다. 

그리고 새로운 앱을 만듭니다. 

$ heroku create
Creating app... done, ⬢ quiet-citadel-80656
https://quiet-citadel-80656-d411fa0f58d4.herokuapp.com/ | https://git.heroku.com/radiant-everglades-49858.git

Heroku container registry에 로그인합니다. 

$ heroku container:login

 mini plan으로 postgres database에 프로비저닝 합니다. 

$ heroku addons:create heroku-postgresql:mini --app quiet-citadel-80656

프로덕션 이미지를 빌드하고 태그를 지정합니다. 

registry.heroku.com/<app>/<process-type>

막 생성한 헤로쿠 앱의 이름으로 `<app>` 부분에 지정합니다. `<process-type>`은 web으로 지정합니다.

$ docker build -f project/Dockerfile.prod -t registry.heroku.com/quiet-citadel-80656/web ./project

로컬 테스트를 하려면 컨테이너를 기동해보겠습니다. 

$ docker run --name fastapi-tdd -e PORT=8765 -e DATABASE_URL=sqlite://sqlite.db -p 5003:8765 registry.heroku.com/quiet-citadel-80656/web:latest

아래와 같은 로그를 확인 할 수 있어야 합니다. 

[2024-02-06 12:22:08 +0000] [8] [INFO]  Starting gunicorn 21.0.1
[2024-02-06 12:22:08 +0000] [8] [INFO]  Listening at: http://0.0.0.0:8765 (8)
[2024-02-06 12:22:08 +0000] [8] [INFO]  Using worker: uvicorn.workers.UvicornWorker
[2024-02-06 12:22:08 +0000] [10] [INFO] Booting worker with pid: 10
[2024-02-06 12:22:08 +0000] [10] [INFO] Started server process [10]
[2024-02-06 12:22:08 +0000] [10] [INFO] Waiting for application startup.
[2024-02-06 12:22:08 +0000] [10] [INFO] Application startup complete.

http://localhost:5003/ping/ 엔드포인트를 확인하면 아래와 같이 확인 할 수 있습니다. 

{
  "ping": "pong!",
  "environment": "prod",
  "testing": false
}

아래 명령어로 특정 컨테이너를 강제 삭제합니다. 

$ docker rm fastapi-tdd -f

레지스트리에 이미지를 푸시합니다. 

$ docker push registry.heroku.com/quiet-citadel-80656/web:latest

이미지를 배포합니다. 

$ heroku container:release web --app quiet-citadel-80656

 

  quiet-citadel-80656 로 앱 이름을 대체하였지만 본인의 앱이름을 확인하여서 이에 맞게 명령어를 수행해주세요. 

컨테이너가 실행되고  https://APP_NAME-IDENTIFIER.herokuapp.com/ping 엔드포인트를 통해서 정상적으로 통신이 이루어 짐을 확인 할 수 있습니다. 

M1 or M2 사용자의 경우 Exec format error가 발생 할 수 있으므로 buildx 명령어를 사용해야 할 수 있습니다. 

$ docker buildx build --platform linux/amd64 -f project/Dockerfile.prod -t registry.heroku.com/quiet-citadel-80656/web ./project

이번에는 마이그레이션을 적용하겠습니다. 

$ heroku run aerich upgrade --app quiet-citadel-80656

 

'summaries' 엔드포인트가 잘 작동되는지 확인해봅니다. 

 

/summaries GET READ get all summaries
/summaries/:id GET READ get single summary
/summaries POST CREATE add a summary

 

HTTPie를 이용하여 HTTP POST 요청을 통해 새로운 리소스를 만들어봅니다. 

$ http --json POST https://quiet-citadel-80656-d411fa0f58d4.herokuapp.com/summaries/ url=https://testdriven.io

정상적으로 201 반환값을 볼 수 있습니다. 

HTTP/1.1 201 Created
Connection: keep-alive
Content-Length: 38
Content-Type: application/json
Date: Sun, 30 Oct 2022 14:15:53 GMT
Server: uvicorn
Via: 1.1 vegur

{
    "id": 1,
    "url": "https://testdriven.io"
}

 

 https://APP_NAME-IDENTIFIER.herokuapp.com/docs  에서도 잘 작동하는지 확인합니다. 

저작자표시 (새창열림)

'프로그래밍 언어 > 파이썬' 카테고리의 다른 글

코루틴이란?  (0) 2024.03.20
List와 Tuple의 차이  (0) 2024.03.20
FastAPI를 이용한 TDD 개발 - 8  (0) 2024.03.14
FastAPI를 이용한 TDD 개발 - 6  (0) 2024.03.14
FastAPI를 이용한 TDD 개발 - 5  (0) 2024.03.14
'프로그래밍 언어/파이썬' 카테고리의 다른 글
  • 코루틴이란?
  • List와 Tuple의 차이
  • FastAPI를 이용한 TDD 개발 - 8
  • FastAPI를 이용한 TDD 개발 - 6
hyeseong-dev
hyeseong-dev
안녕하세요. 백엔드 개발자 이혜성입니다.
  • hyeseong-dev
    어제 오늘 그리고 내일
    hyeseong-dev
  • 전체
    오늘
    어제
    • 분류 전체보기 (284)
      • 여러가지 (108)
        • 알고리즘 & 자료구조 (72)
        • 오류 (4)
        • 이것저것 (29)
        • 일기 (2)
      • 프레임워크 (39)
        • 자바 스프링 (39)
        • React Native (0)
      • 프로그래밍 언어 (38)
        • 파이썬 (30)
        • 자바 (3)
        • 스프링부트 (5)
      • 운영체제 (0)
      • DB (17)
        • SQL (0)
        • Redis (17)
      • 클라우드 컴퓨팅 (2)
        • 도커 (2)
        • AWS (0)
      • 스케쥴 (65)
        • 세미나 (0)
        • 수료 (0)
        • 스터디 (24)
        • 시험 (41)
      • 트러블슈팅 (1)
      • 자격증 (0)
        • 정보처리기사 (0)
      • 재태크 (5)
        • 암호화폐 (5)
        • 기타 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Spring Boot
    취업리부트
    Python
    백준
    docker
    AWS
    Spring WebFlux
    EC2
    RDS
    ecs
    reactor
    #개발자포트폴리오 #개발자이력서 #개발자취업 #개발자취준 #코딩테스트 #항해99 #취리코 #취업리부트코스
    프로그래머스
    mybatis
    celery
    OOP
    DP
    java
    그리디
    자바
    FastAPI
    항해99
    파이썬
    시험
    완전탐색
    WebFlux
    Docker-compose
    spring
    Redis
    SAA
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
hyeseong-dev
FastAPI를 이용한 TDD 개발 - 7
상단으로

티스토리툴바