FastAPI in Docker — 공식 배포 가이드 (FastAPI Docs)

Source: https://fastapi.tiangolo.com/deployment/docker/ Type: Article By: Sebastián Ramírez (tiangolo) Valid as of: 2026-04-26

핵심 Takeaway

  • 컨테이너(Container): 경량 독립 환경에서 호스트의 Linux 커널 공유하여 애플리케이션 + 의존성 격리 운영
  • Dockerfile: 정적 이미지 블루프린트 (파일, 환경변수, 시작 명령 정의)
  • 레이어 캐싱 최적화: requirements.txt 먼저 복사 → RUN pip → 앱 코드 나중에 복사 (의존성 변경 빈도 < 코드 변경 빈도)
  • 기본 Dockerfile 구조: FROM (기본 이미지) → WORKDIR (작업 디렉토리) → COPY (파일) → RUN (설치) → CMD (시작)
  • CMD exec form 필수: CMD ["fastapi", "run", "app/main.py"] (shell form 금지: CMD fastapi run app/main.py)
  • 여러 워커: CMD ["fastapi", "run", "app/main.py", "--workers", "4"]로 다중 프로세스 병렬 실행
  • HTTPS는 외부 처리: 컨테이너는 HTTP(포트 80)만, Traefik/Nginx 역프록시에서 HTTPS/SSL 담당

상세 요약

컨테이너 & 이미지의 기본 개념

컨테이너 (Container):

  • 정의: 애플리케이션 및 모든 의존성(라이브러리, 설정)을 격리된 환경에 패키징한 것
  • 특징: 호스트 Linux 커널 공유 → 가볍고 빠름 (VM보다 오버헤드 작음)
  • 격리: 네트워크, 파일시스템, 프로세스가 서로 독립적

컨테이너 이미지 (Container Image):

  • 정의: 컨테이너 생성 시 사용할 정적 패키지
  • 포함 요소: 파일 시스템, 환경변수, 시작 명령(CMD)
  • 배포: 이미지는 어디서나 동일한 컨테이너 생성 (재현성 보장)

Dockerfile 작성 및 최적화

기본 디렉토리 구조:

.
├── app
│   ├── __init__.py
│   └── main.py
├── Dockerfile
└── requirements.txt

Dockerfile 구조 (6단계):

FROM python:3.14           # 1. 기본 이미지 선택
WORKDIR /code              # 2. 컨테이너 내 작업 디렉토리
COPY ./requirements.txt /code/requirements.txt  # 3. 의존성 목록 복사
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt  # 4. 의존성 설치
COPY ./app /code/app       # 5. 애플리케이션 코드 복사
CMD ["fastapi", "run", "app/main.py", "--port", "80"]  # 6. 시작 명령 (exec form)

각 단계의 목적:

단계명령설명
1FROM python:3.14공식 Python 베이스 이미지 사용 (경량화된 -slim 권장)
2WORKDIR /code컨테이너 내 모든 파일 작업의 루트 (상대 경로 기준점)
3COPY requirements.txt /code/의존성 목록만 먼저 복사
4RUN pip install의존성 설치 (캐싱됨: requirements.txt 미변경 시 재사용)
5COPY ./app /code/app애플리케이션 코드 복사 (자주 변경되므로 마지막)
6CMD ["fastapi", "run", ...]컨테이너 시작 시 실행할 명령

레이어 캐싱 & 빌드 최적화

Docker 빌드는 각 명령을 하나의 “레이어”로 캐시한다. 이전 결과가 변경되지 않으면 캐시 재사용.

캐싱 최적화 핵심:

  • requirements.txt: 변경 빈도 낮음 (수주 단위) → 빌드 초반
  • 애플리케이션 코드: 변경 빈도 높음 (매일) → 빌드 후반

결과:

  1. 의존성 미변경 시: RUN pip install 레이어 캐시 재사용 → 빌드 시간 10초
  2. 코드 변경 시: 5번 단계부터만 재실행 → 나머지 캐시 재사용 → 빌드 시간 20초

캐시 효율 낮은 패턴 (피하기):

# ❌ 나쁜 예: 의존성 먼저, 코드는 함께
COPY . /code/
RUN pip install -r requirements.txt

→ 코드 1줄만 변경해도 RUN pip install부터 재실행 (느림)

이미지 빌드 & 컨테이너 실행

이미지 빌드:

docker build -t myimage .
  • -t myimage: 이미지 이름 지정 (태그)
  • .: 현재 디렉토리의 Dockerfile 사용

컨테이너 실행:

docker run -d --name mycontainer -p 80:80 myimage
  • -d: 백그라운드 실행
  • --name mycontainer: 컨테이너 이름 지정
  • -p 80:80: 호스트 포트 80 → 컨테이너 포트 80 포워딩

다중 워커(Workers) 설정

기본: FastAPI는 단일 워커(단일 프로세스) 실행 → 동시 요청 처리 제한

다중 워커 활성화:

CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
  • 4개 워커 프로세스 병렬 실행
  • 동시 요청 처리량 4배 증가
  • CPU 다중 코어 활용

CMD 형식: Exec form vs Shell form

올바른 형식 (Exec form):

CMD ["fastapi", "run", "app/main.py", "--port", "80"]
  • 형태: JSON 배열
  • 동작: fastapi 프로세스를 직접 실행 (PID 1)
  • 장점: 시그널(SIGTERM) 정상 처리 → 컨테이너 우아한 종료

잘못된 형식 (Shell form):

CMD fastapi run app/main.py --port 80
  • 형태: 문자열
  • 동작: /bin/sh에서 실행 (PID 1은 shell)
  • 문제: 시그널 미수신 → 강제 종료(SIGKILL) → 우아하지 않음

HTTPS/SSL 처리: 외부 레이어

FastAPI 컨테이너는 HTTP(포트 80)만 처리. HTTPS와 SSL/TLS 인증서는 외부 계층에서 관리:

  • Traefik: 리버스 프록시 + 자동 인증서 갱신 (Let’s Encrypt)
  • Nginx: 경량 리버스 프록시
  • 클라우드 제공자: AWS ALB, Google Cloud Load Balancer 등

구조:

클라이언트 ─(HTTPS 443)─ Traefik ─(HTTP 80)─ FastAPI
         ↑
    SSL/TLS 인증서 관리

선행 개념

이 개념을 배우기 전에 필수로 알아야 할 것:

  1. Module 1-1 → python-type-hints-fastapi: FastAPI의 타입 기반 검증 이해
    • 왜?: Dockerfile 작성 시 FastAPI 애플리케이션의 구조를 이해해야 함
  2. Module 1-4 → pydantic-validation-velog: Pydantic 모델을 통한 요청/응답 검증
    • 왜?: FastAPI 애플리케이션이 Pydantic 모델을 포함하고 있으므로, 의존성 설치 시 이를 고려해야 함

후속 개념 (이 개념이 선행)

이 개념을 배운 후 다음 단계:

  1. Module 6-2 → docker-compose-multi-service-orchestration: 여러 서비스(FastAPI + DB + Traefik) 통합
    • 이 소스: 단일 FastAPI 컨테이너만 다룸
    • 다음 단계: Docker Compose로 전체 스택 관리
  2. Module 4-2 → fastapi-docker-best-practices-production: 프로덕션 배포 모범 사례

연결되는 위키 페이지