---
name: dockerfile-gen
description: |
  트리거: "dockerfile 만들어줘", "도커 설정", "docker 설정해줘", "컨테이너화", "dockerize"
  수행: 프로젝트 구조 분석 → 멀티스테이지 Dockerfile + docker-compose.yml 생성. 레이어 캐싱·보안 최적화(non-root user) 적용
  출력: Dockerfile, docker-compose.yml, .dockerignore
---

# Dockerfile Generator

## 목적

프로젝트의 언어, 프레임워크, 런타임을 분석하여 프로덕션 수준의 멀티스테이지 Dockerfile과 docker-compose.yml을 생성한다.
레이어 캐싱 최적화, non-root 사용자 실행, 최소 이미지 크기를 기본으로 적용한다.

## 실행 절차

1. **프로젝트 분석**: package.json / pyproject.toml / go.mod / pom.xml 등에서 언어·런타임·빌드 커맨드 파악
2. **베이스 이미지 선택**: 언어별 최적 alpine/slim 이미지 선택
3. **멀티스테이지 설계**: deps → builder → runner 단계 분리
4. **레이어 캐싱 최적화**: 의존성 파일 먼저 COPY → 설치 → 소스 COPY 순서 적용
5. **보안 강화**: non-root 사용자 생성, 최소 권한 원칙, 시크릿 노출 방지
6. **docker-compose.yml 생성**: 서비스·네트워크·볼륨 정의
7. **.dockerignore 생성**: 불필요 파일 제외

## 출력 형식

### Node.js (Next.js) 예시

```dockerfile
# Dockerfile
# ── Stage 1: 의존성 설치 ──────────────────────────────────────
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

# 패키지 파일만 먼저 복사 (레이어 캐싱 최적화)
COPY package.json package-lock.json* ./
RUN npm ci --only=production --ignore-scripts

# ── Stage 2: 빌드 ─────────────────────────────────────────────
FROM node:20-alpine AS builder
WORKDIR /app

COPY --from=deps /app/node_modules ./node_modules
COPY . .

# 빌드 시점 환경변수
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
ENV NEXT_TELEMETRY_DISABLED=1

RUN npm run build

# ── Stage 3: 프로덕션 런타임 ──────────────────────────────────
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000

# non-root 사용자 생성 (보안)
RUN addgroup --system --gid 1001 nodejs && \
    adduser  --system --uid 1001 nextjs

# 필요한 파일만 복사
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget -qO- http://localhost:3000/api/health || exit 1

CMD ["node", "server.js"]
```

```yaml
# docker-compose.yml
version: '3.9'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: runner
      args:
        NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:3000}
    image: myapp:latest
    container_name: myapp
    restart: unless-stopped
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
    networks:
      - app-network
    depends_on:
      db:
        condition: service_healthy
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M

  db:
    image: postgres:16-alpine
    container_name: myapp-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-myapp}
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?DB password required}
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - app-network
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-postgres}']
      interval: 10s
      timeout: 5s
      retries: 5

  nginx:
    image: nginx:1.25-alpine
    container_name: myapp-nginx
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    networks:
      - app-network
    depends_on:
      - app

networks:
  app-network:
    driver: bridge

volumes:
  postgres-data:
```

```gitignore
# .dockerignore
.git
.gitignore
.env*
!.env.example
node_modules
npm-debug.log*
.next
out
coverage
.nyc_output
*.test.*
*.spec.*
__tests__
.storybook
storybook-static
README.md
docs
.DS_Store
Thumbs.db
```

### Python (FastAPI) 예시

```dockerfile
# Dockerfile
FROM python:3.12-slim AS base
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1

# ── Stage 1: 의존성 빌드 ──────────────────────────────────────
FROM base AS builder
WORKDIR /app

RUN pip install uv
COPY pyproject.toml uv.lock* ./
RUN uv pip install --system --no-dev -r pyproject.toml

# ── Stage 2: 프로덕션 런타임 ──────────────────────────────────
FROM base AS runner
WORKDIR /app

# non-root 사용자
RUN groupadd -r appuser && useradd -r -g appuser appuser

COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --chown=appuser:appuser . .

USER appuser

EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s \
  CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
```

## 사용 예시

**입력:**
> "Go로 만든 API 서버 Dockerfile 만들어줘. PostgreSQL이랑 Redis도 같이 사용해."

**출력:**
- `Dockerfile` - Go 멀티스테이지 (build → distroless runner)
- `docker-compose.yml` - app + postgres + redis + healthcheck
- `.dockerignore` - Go 빌드 아티팩트 제외

## 주의사항

- `.env` 파일은 절대 이미지에 포함하지 않음 — `--env-file` 또는 시크릿 관리 도구 사용
- `RUN` 명령은 체이닝(`&&`)으로 레이어 수 최소화
- `COPY . .`는 반드시 의존성 설치 이후에 위치 (캐시 무효화 방지)
- 프로덕션 이미지에 빌드 도구(`gcc`, `make` 등) 잔류 금지
- `HEALTHCHECK` 필수 추가 — 오케스트레이터(K8s, Swarm) 연동
- `docker-compose.yml`의 시크릿은 `${VAR:?error}` 문법으로 누락 시 실패 처리
