FastAPI 애플리케이션은 별도의 빌드 단계 없이 ASGI 서버로 실행해 배포합니다. 이 장에서는 fastapi run과 Uvicorn으로 운영 서버를 띄우는 방법, 워커 프로세스 수 정하기, 컨테이너 이미지 만들기, 리버스 프록시 뒤에서 실행할 때 주의할 점을 다룹니다.
fastapi run으로 운영 서버 실행
fastapi dev는 개발용이고, 운영 환경에서는 fastapi run을 씁니다. 자동 재시작이 꺼지고 기본적으로 모든 네트워크 인터페이스(0.0.0.0)의 8000번 포트에서 요청을 받습니다.
# 프로세스 하나
fastapi run app/main.py
# 포트를 바꾸고 워커 프로세스 4개로 실행
fastapi run app/main.py --port 80 --workers 4
fastapi run은 내부에서 Uvicorn을 사용합니다. Uvicorn을 직접 실행해도 결과는 같으며, 이때는 파일 경로 대신 모듈:변수 형식으로 앱을 지정합니다.
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
워커 수와 프로세스 관리
Python 프로세스 하나는 사실상 CPU 코어 하나만 활용하므로, 여러 코어를 쓰려면 --workers로 프로세스를 여러 개 띄웁니다. 처음에는 코어 수 정도에서 시작해 부하 시험으로 조정합니다. 워커마다 메모리를 따로 쓰므로 큰 모델을 불러오는 앱은 메모리 사용량도 함께 살펴야 합니다.
서버에 직접 배포한다면 systemd 같은 프로세스 관리자로 서버가 재부팅되거나 프로세스가 죽었을 때 다시 시작되도록 합니다. Kubernetes처럼 클러스터가 컨테이너 수를 조절하는 환경에서는 컨테이너마다 프로세스 하나만 띄우고 복제본 수로 확장하는 것이 일반적입니다.
컨테이너 이미지 만들기
컨테이너로 배포하면 실행 환경을 그대로 재현할 수 있습니다. 공식 문서가 권하는 방식은 Python 공식 이미지에서 시작해 의존성을 먼저 설치하고 코드를 나중에 복사하는 것입니다. 이렇게 하면 코드만 바뀌었을 때 의존성 설치 단계의 캐시를 재사용합니다.
FROM python:3-slim
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
실제 프로젝트에서는 개발에 쓰는 것과 같은 Python 버전을 태그에 명시해 고정하는 것이 좋습니다. CMD는 위처럼 배열(exec) 형식으로 써야 컨테이너가 멈출 때 종료 신호가 앱에 제대로 전달되어 lifespan의 정리 코드가 실행됩니다.
docker build -t hello-fastapi .
docker run -d --name hello -p 8000:80 --env-file .env hello-fastapi
.env 파일은 이미지에 넣지 않고 실행할 때 --env-file이나 플랫폼의 비밀 값 기능으로 넘깁니다. .dockerignore에 .venv, .env, __pycache__를 넣어 두면 이미지가 가벼워집니다.
리버스 프록시 뒤에서 실행
운영 환경에서는 보통 Nginx, Traefik, 클라우드 로드 밸런서 같은 리버스 프록시가 HTTPS 인증서를 처리하고 요청을 앱으로 넘깁니다. 이때 앱이 원래 클라이언트의 주소와 https 프로토콜을 알 수 있도록 프록시가 X-Forwarded-* 헤더를 붙이고, 앱 서버는 신뢰하는 프록시에서 온 헤더만 받아들이게 합니다.
server {
listen 443 ssl;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
uvicorn app.main:app --host 127.0.0.1 --port 8000 --proxy-headers --forwarded-allow-ips="127.0.0.1"
프록시가 /api 같은 경로 접두사를 붙여 앱으로 넘긴다면 FastAPI(root_path="/api")나 --root-path /api 옵션으로 알려 주어야 /docs의 문서와 링크가 올바른 주소를 씁니다.
배포 전 점검
- 운영에서는
fastapi dev나 --reload를 쓰지 않습니다. - 비밀 값은 환경 변수로 넘기고 저장소와 이미지에 넣지 않습니다.
- 데이터베이스 스키마 변경은 Alembic 같은 마이그레이션 도구로 적용합니다.
- 공개 API가 아니라면
FastAPI(docs_url=None, redoc_url=None)로 문서 화면을 끌 수 있습니다. /health 같은 상태 확인 엔드포인트를 두어 로드 밸런서와 오케스트레이터가 쓰게 합니다.
정리
- 운영 서버는
fastapi run 또는 uvicorn으로 실행하고, --workers로 프로세스 수를 정합니다. - 컨테이너 이미지는 의존성을 먼저 설치하고 코드를 나중에 복사해 캐시를 활용합니다.
- 리버스 프록시 뒤에서는 프록시 헤더와
root_path를 올바르게 설정합니다.
더 자세한 내용은 공식 문서를 참고하세요.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.