Use Cases (업데이트: 2026. 6. 3.)

Claude Code와 Docker 실전: Compose, Volume, Network, CI 빌드

Claude Code로 Dockerfile, Compose, 로컬 환경, CI 이미지 빌드를 안전하게 정리합니다.

Claude Code와 Docker 실전: Compose, Volume, Network, CI 빌드

Claude Code에 맡길 범위를 먼저 정하기

Claude Code에 “Docker로 만들어줘”라고만 말하면 한 번은 실행되지만 리뷰하기 어려운 Dockerfile이 나올 수 있습니다. Docker는 애플리케이션 실행 환경을 고정하는 도구입니다. image는 실행 템플릿, container는 실제 실행 인스턴스, volume은 컨테이너 밖에 남기는 데이터 저장소, network는 컨테이너가 서비스 이름으로 통신하는 길입니다.

실무에서는 Dockerfile 하나만 보지 않습니다. Dockerfile, docker-compose.yml, .dockerignore, 환경 변수, health check, CI build를 한 묶음으로 봐야 합니다. 작업 중에는 Dockerfile reference, Compose file reference, Docker build best practices, Docker Build GitHub Actions, Claude Code overview를 함께 확인하세요.

CI까지 정리한다면 Claude Code CI/CD setup을 같이 보면 좋습니다. 권한과 안전 경계는 Claude Code approval and sandbox guideClaude Code security best practices로 이어집니다.

4가지 실전 사용 사례

Docker 연동의 목적은 멋진 개발 환경이 아니라 재현성을 높이는 것입니다. 어떤 문제를 해결할지 먼저 적고 Claude Code에 맡기세요.

사용 사례Docker가 고정하는 것Claude Code에 요청할 작업
신규 멤버 온보딩Node.js, PostgreSQL, Redis, 포트, 시작 명령docker compose up으로 stack이 뜨게 만들기
운영 환경에 가까운 디버깅환경 변수, 서비스 이름, health check, 시작 순서로컬과 운영의 차이를 표로 정리하기
PR 검증Dockerfile, lockfile, build cache, CI logimage build만 확인하는 workflow 추가
교육과 인수인계명령, 실패 패턴, 복구 절차CLAUDE.md와 README에 운영 규칙 작성

수익과 연결된 SaaS나 콘텐츠 사이트에서는 이 차이가 큽니다. 결제, 문의 폼, 관리자 화면, 상품 페이지가 특정 노트북에서만 동작하면 매출이 검증되지 않은 로컬 상태에 의존합니다. 개인은 ClaudeCodeLab products로 시작할 수 있고, 팀은 실제 저장소에 맞춘 Claude Code training and consultation으로 권한, CI, review 기준까지 정리할 수 있습니다.

Claude Code에 줄 프롬프트

첫 요청에는 대상, 만들어야 할 파일, 금지 사항, 검증 방법을 함께 넣습니다. 그래야 그럴듯하지만 위험한 Docker 구성을 줄일 수 있습니다.

Dockerize this Node.js + TypeScript API.

Context:
- pnpm is the package manager.
- The app listens on port 3000.
- GET /health returns 200.
- Local development needs PostgreSQL 16 and Redis 7.

Create:
- Production multi-stage Dockerfile
- docker-compose.yml for local development
- .dockerignore
- Docker-related package.json scripts
- GitHub Actions workflow that only verifies docker build

Constraints:
- Do not run the production container as root.
- Do not COPY .env files or secrets into the image.
- Explain the volume and network choices for the README.
- Include verification commands and how to inspect failures.

multi-stage build는 빌드용 환경과 실행용 환경을 나누는 방식입니다. TypeScript 컴파일 도구는 build stage에 두고, 최종 image에는 production dependencies와 dist만 남깁니다. 크기도 줄고 공격면도 작아집니다.

바로 사용할 수 있는 Dockerfile

아래 예시는 src/index.tsdist/index.js로 빌드하는 Node.js API를 가정합니다. dev stage는 로컬 Compose용이고 runner stage는 운영 image입니다.

# syntax=docker/dockerfile:1

FROM node:22-bookworm-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
WORKDIR /app
RUN corepack enable

FROM base AS dev
ENV NODE_ENV=development
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
CMD ["pnpm", "dev"]

FROM base AS deps
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

FROM deps AS build
COPY tsconfig.json ./
COPY src ./src
RUN pnpm build

FROM base AS prod-deps
ENV NODE_ENV=production
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod && pnpm store prune

FROM base AS runner
ENV NODE_ENV=production
RUN groupadd --system --gid 1001 nodejs \
  && useradd --system --uid 1001 --gid nodejs appuser
COPY --from=prod-deps --chown=appuser:nodejs /app/node_modules ./node_modules
COPY --from=build --chown=appuser:nodejs /app/dist ./dist
COPY --chown=appuser:nodejs package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD node -e "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["node", "dist/index.js"]

Claude Code에 리뷰를 맡길 때는 secret이 image에 들어갈 수 있는지, COPY 순서가 cache를 깨지 않는지, runtime image에 devDependencies가 남아 있지 않은지를 확인하게 하세요.

Compose의 Volume과 Network 이해하기

Compose는 여러 컨테이너를 함께 띄우는 설정입니다. 이 예시에서는 API, PostgreSQL, Redis가 같은 network에 있으므로 API는 postgres, redis라는 서비스 이름으로 접근합니다. Volume은 컨테이너가 삭제되어도 데이터를 남기는 장치입니다. pgdata는 DB 파일을 보존하고, api_node_modules는 호스트의 node_modules가 Linux 컨테이너 의존성을 덮어쓰는 문제를 막습니다.

services:
  api:
    build:
      context: .
      target: dev
    command: pnpm dev
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: development
      DATABASE_URL: postgres://app:app@postgres:5432/app
      REDIS_URL: redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    volumes:
      - .:/app
      - api_node_modules:/app/node_modules
    healthcheck:
      test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
      interval: 10s
      timeout: 3s
      retries: 5

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: app
      POSTGRES_DB: app
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 5s
      timeout: 3s
      retries: 10

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  pgdata:
  api_node_modules:

depends_on은 시작 순서를 다룹니다. DB가 실제로 연결 가능한지는 별도 문제이므로 healthcheckcondition: service_healthy를 같이 사용합니다.

Secret을 build context 밖에 두기

먼저 .dockerignore를 작성합니다. build context를 줄이고 .env 같은 민감한 파일이 image로 들어가는 사고를 막습니다.

.git
node_modules
dist
coverage
.env
.env.*
!.env.example
npm-debug.log*
pnpm-debug.log*
Dockerfile*
docker-compose*.yml

팀이 같은 명령을 쓰도록 package.json scripts도 남깁니다.

{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc -p tsconfig.json",
    "start": "node dist/index.js",
    "docker:dev": "docker compose up --build",
    "docker:check": "bash scripts/docker-check.sh"
  },
  "dependencies": {
    "@fastify/redis": "latest",
    "fastify": "latest",
    "pg": "latest"
  },
  "devDependencies": {
    "tsx": "latest",
    "typescript": "latest"
  }
}

반복 가능한 검증 스크립트

확인을 매번 손으로 하면 빠뜨리기 쉽습니다. scripts/docker-check.sh로 남겨 두면 Claude Code와 CI가 같은 검증 절차를 사용할 수 있습니다.

#!/usr/bin/env bash
set -euo pipefail

docker compose build api
docker compose up -d postgres redis api

cleanup() {
  docker compose down
}
trap cleanup EXIT

for attempt in {1..30}; do
  if curl -fsS http://127.0.0.1:3000/health >/dev/null; then
    echo "healthcheck ok"
    exit 0
  fi
  echo "waiting for api... ${attempt}/30"
  sleep 2
done

docker compose logs api
exit 1

이 스크립트는 build, stack 시작, /health 대기, 실패 시 로그 출력까지 처리합니다.

CI는 먼저 build만 검증하기

처음에는 registry에 push하지 말고 image build만 확인합니다. push, signing, vulnerability scan, SBOM은 기본이 안정된 뒤 추가합니다.

name: docker-build

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/build-push-action@v7
        with:
          context: .
          target: runner
          push: false
          tags: claude-code-docker-sample:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Claude Code에는 이 workflow가 실제로 push하지 않는지, 권한이 과하지 않은지, cache가 비어도 build되는지 설명하게 하세요.

자주 터지는 실패

가장 위험한 실패는 .env를 image에 복사하는 것입니다. secret이 registry에 들어가면 회수 비용이 큽니다. .dockerignore, CI secrets, build log를 함께 확인해야 합니다.

두 번째는 호스트의 node_modules를 컨테이너에 덮어쓰는 문제입니다. macOS, Windows, Linux의 native package는 다를 수 있습니다. named volume으로 분리하면 이 문제가 줄어듭니다.

세 번째는 API가 DB보다 먼저 떠서 연결에 실패하는 상황입니다. depends_on만 믿지 말고 DB health check와 애플리케이션 retry를 같이 설계합니다.

네 번째는 운영 컨테이너를 root로 실행하는 것입니다. 데모에서는 문제가 없어 보여도 실제 서비스에서는 위험 범위가 커집니다. Claude Code에 non-root를 증명하는 Dockerfile 라인을 짚게 하세요.

안전한 개발 순서

권장 순서는 저장소 조사, runtime 의존성 정리, .dockerignore, local Compose, production Dockerfile, 검증 스크립트, CI입니다. 각 단계 후에는 사람이 git diff를 읽고 Claude Code에게 changed files, reason, verification command, remaining risk를 짧게 쓰게 합니다.

이 방식은 session handoff template와도 잘 맞습니다. Docker 연동은 일회성 파일 생성이 아니라 팀이 공유하는 반복 가능한 개발 습관이 되어야 합니다.

실제 적용에서 얻은 결론

실제로는 Claude Code 작업을 작게 나눌수록 결과가 좋아졌습니다. .dockerignore, Compose, health check, CI 순서로 진행하면 리뷰가 쉬웠습니다. 특히 named node_modules volume과 DB health gate는 초보자가 자주 겪는 “내 PC에서만 된다”와 “API는 켜졌는데 Postgres에 연결되지 않는다” 문제를 줄여줍니다.

#Claude Code #Docker #containers #DevOps #infrastructure
무료

무료 PDF: Claude Code 치트시트

이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.

개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.

Masa

작성자 소개

Masa

Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.