DockerDocker 기초강의 6개 중 6번째난이도 기초

Docker 실전 프로젝트 — 전체 스택 컨테이너화

발행 읽는 시간 약 1 분

  • Docker
  • 프로젝트
  • FastAPI
  • PostgreSQL
  • Nginx
  • 전체스택

강의 소개

Docker 기초 시리즈 총정리 프로젝트입니다. FastAPI 백엔드, PostgreSQL, Redis, Nginx를 Docker Compose로 구성해 로컬 개발부터 프로덕션까지 일관된 환경을 만듭니다.

프로젝트 구조#

Text
my-app/
├── backend/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── app/
│       └── main.py
├── nginx/
│   └── nginx.conf
├── docker-compose.yml          # 개발 환경
├── docker-compose.prod.yml     # 프로덕션 환경
└── .env.example

Backend Dockerfile (멀티스테이지)#

Dockerfile
# backend/Dockerfile
FROM python:3.12-slim AS base

WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

# 의존성 설치 스테이지
FROM base AS dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 개발 스테이지
FROM dependencies AS development
COPY requirements-dev.txt .
RUN pip install --no-cache-dir -r requirements-dev.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

# 프로덕션 스테이지
FROM dependencies AS production
COPY . .
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

FastAPI 앱#

Python
# backend/app/main.py
from fastapi import FastAPI
from contextlib import asynccontextmanager
import asyncpg
import redis.asyncio as aioredis
import os

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.db = await asyncpg.create_pool(os.environ["DATABASE_URL"])
    app.state.cache = await aioredis.from_url(os.environ["REDIS_URL"])
    yield
    await app.state.db.close()
    await app.state.cache.close()

app = FastAPI(lifespan=lifespan)

@app.get("/health")
async def health():
    return {"status": "ok"}

@app.get("/users")
async def list_users():
    async with app.state.db.acquire() as conn:
        rows = await conn.fetch("SELECT id, name, email FROM users ORDER BY id")
        return [dict(r) for r in rows]

개발 환경 docker-compose.yml#

YAML
version: "3.9"

services:
  api:
    build:
      context: ./backend
      target: development
    ports:
      - "8000:8000"
    env_file: .env
    volumes:
      - ./backend:/app       # 소스 실시간 반영
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"  # 개발 시 직접 접속 허용
    healthcheck:
      test: pg_isready -U ${DB_USER}
      interval: 5s
      retries: 10

  cache:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  adminer:
    image: adminer
    ports:
      - "8080:8080"
    profiles: [tools]

volumes:
  db_data:

Nginx 설정#

Nginx
# nginx/nginx.conf
events { worker_connections 1024; }

http {
    upstream api {
        server api:8000;
    }

    server {
        listen 80;

        # API 요청
        location /api/ {
            proxy_pass http://api/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 정적 파일
        location / {
            root /usr/share/nginx/html;
            try_files $uri $uri/ /index.html;
        }
    }
}

프로덕션 docker-compose.prod.yml#

YAML
services:
  api:
    image: ${REGISTRY}/my-app-api:${VERSION:-latest}
    restart: always
    env_file: .env.prod

  db:
    image: postgres:16-alpine
    restart: always
    volumes:
      - db_data:/var/lib/postgresql/data
    env_file: .env.prod
    # 포트 외부 노출 없음

  cache:
    image: redis:7-alpine
    restart: always

  nginx:
    image: nginx:alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.prod.conf:/etc/nginx/nginx.conf:ro
      - certs:/etc/letsencrypt

volumes:
  db_data:
  certs:

Docker 기초 시리즈 정리#

편주제
1편Docker 개념, 컨테이너 vs VM
2편Dockerfile 작성, 멀티스테이지
3편Docker Compose, 멀티 서비스
4편볼륨과 네트워크
5편레지스트리와 CI/CD
6편실전 프로젝트

Docker를 익히면 개발 환경 설정 시간이 docker compose up 한 줄로 줄어듭니다.

다음은 LLM 파인튜닝 — 모델을 내 데이터로 커스터마이징하는 방법을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.