컨테이너화 (Containerization)
애플리케이션과 의존성을 격리된 환경에 패키징하여, 개발·스테이징·프로덕션에서 동일하게 실행 가능하게 하는 기술.
설명
컨테이너화는 다음 문제를 해결한다:
문제: “내 컴퓨터(Mac/Windows)에서는 되는데 서버(Linux)에서 안 된다”
- 개발 환경: Python 3.9, 라이브러리 v1.0
- 서버 환경: Python 3.11, 라이브러리 v2.0
- 결과: 호환성 오류, 운영 비용 증가
해결책: 애플리케이션 + 의존성을 하나의 “컨테이너”로 패키징
- Dockerfile = 인프라 코드화 (git 버전 관리 가능)
- 동일한 이미지 → 어디서나 동일한 실행 환경
핵심 개념
컨테이너 (Container)
호스트 Linux 커널을 공유하면서 격리된 환경:
- 파일 시스템 격리
- 네트워크 격리
- 프로세스 격리
이점:
- 경량 (VM의 1/10 크기)
- 빠른 시작 (초 단위)
- 확장성 (여러 인스턴스 병렬 실행)
이미지 (Image)
컨테이너 생성 시 사용할 정적 패키지:
- 파일 시스템 스냅샷
- 환경변수
- 시작 명령
레이어 (Layer)
Dockerfile의 각 명령은 하나의 “레이어”로 캐시된다:
FROM python:3.11-slim # 레이어 1 (베이스 이미지)
COPY requirements.txt . # 레이어 2
RUN pip install -r requirements.txt # 레이어 3 (캐시 키: 레이어 2)
COPY . . # 레이어 4
CMD ["fastapi", "run", "app/main.py"] # 레이어 5캐싱 원리:
- 레이어 1-3 미변경 → 캐시 재사용 (빠름)
- 레이어 4 변경 (코드) → 레이어 4-5만 재실행
캐싱 최적화
변경 빈도 오름차순으로 배열:
| 순서 | 명령 | 변경 빈도 | 캐싱 |
|---|---|---|---|
| 1 | FROM | 거의 안 함 | 거의 항상 재사용 |
| 2 | COPY requirements.txt | 낮음 (수주 단위) | 자주 재사용 |
| 3 | RUN pip install | 낮음 (레이어 2 미변경 시) | 자주 재사용 |
| 4 | COPY . . | 높음 (매일) | 자주 캐시 미스 |
| 5 | CMD | 낮음 | 거의 항상 재사용 |
결과: 빌드 시간 10초 (캐시 hit) vs 100초 (캐시 miss)
5단계 배포 흐름
1단계: Dockerfile 작성
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["fastapi", "run", "app/main.py", "--port", "8000"]2단계: 이미지 빌드
docker build -t myapp:1.0 .3단계: 로컬 테스트 (Docker Desktop)
docker run -p 8000:8000 myapp:1.04단계: 이미지 레지스트리 푸시
docker tag myapp:1.0 myregistry/myapp:1.0
docker push myregistry/myapp:1.0레지스트리: Docker Hub, AWS ECR, Google GCR 등
5단계: 클라우드 배포
- ECS: AWS 관리형 컨테이너 서비스
- GKE: Google Kubernetes Engine
- ACI: Azure Container Instances
- K8s: 자체 관리 오케스트레이션
보안 모범 사례
1. 최신 베이스 이미지
FROM python:3.11-slim # 정기 보안 업데이트알려진 취약점 패치 포함.
2. Non-root 사용자
RUN useradd -m appuser
USER appuser컨테이너 침입 시 피해 최소화.
3. 이미지 스캔
docker scan myapp:1.0CVE(알려진 취약점) 검사 및 업데이트 제시.
4. 민감 정보 외부화
ENV DATABASE_URL= # 비워두기.env 파일로 런타임에 주입.
헬스체크 & 자동 재시작
Docker가 애플리케이션 상태를 정기적으로 확인:
HEALTHCHECK --interval=10s --timeout=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1- 3회 연속 실패 → 컨테이너 자동 재시작
- Kubernetes/ECS는 이 정보로 pod/task 교체
Docker Compose: 다중 서비스
version: '3'
services:
web:
build: .
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
db:
image: postgres:15
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s실행:
docker-compose up모든 서비스 동시 시작, 의존성 자동 관리.
수평 확장 (Horizontal Scaling)
문제: 단일 컨테이너 = 단일 프로세스 = 동시성 제한
해결책: 여러 인스턴스 + 로드 밸런서
[로드 밸런서 (Nginx/Traefik)]
↓
[FastAPI 인스턴스 1]
[FastAPI 인스턴스 2]
[FastAPI 인스턴스 3]
각 인스턴스는 독립적 컨테이너, 병렬 처리 가능.
관련 개념
- reverse-proxy — 여러 컨테이너 앞에 리버스 프록시 배치
- structured-logging — 컨테이너 로그 수집 및 중앙화
실전 적용
docker 의 도구
- Dockerfile 작성
- 이미지 빌드·레지스트리 관리
- 컨테이너 실행·모니터링
fastapi 컨테이너화
- ASGI 웹 프레임워크를 Docker로 배포
- Uvicorn으로 다중 워커 실행
traefik 와의 연계
- 여러 FastAPI 컨테이너 자동 발견
- HTTPS/SSL 종료