Claude Code와 Docker 실전: Compose, Volume, Network, CI 빌드
Claude Code로 Dockerfile, Compose, 로컬 환경, 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 guide와 Claude 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 log | image 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.ts를 dist/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가 실제로 연결 가능한지는 별도 문제이므로 healthcheck와 condition: 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에 연결되지 않는다” 문제를 줄여줍니다.
무료 PDF: Claude Code 치트시트
이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.
개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.
작성자 소개
Masa
Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.
관련 글
Obsidian 메모를 CLAUDE.md로 바꾸는 Claude Code 워크플로
Obsidian 작업 메모를 CLAUDE.md 운영 노트로 정리해 Claude Code 세션의 문맥 반복을 줄입니다.
Claude Code Revenue CTA Routing: 글에서 PDF, Gumroad, 상담으로 보내기
독자 의도에 따라 무료 PDF, Gumroad 상품, 상담으로 나누는 Claude Code CTA 설계입니다.
Claude Code 팀 인계 규칙: 리뷰 증거, 권한, 롤백, 수익 경로까지 넘기는 법
Claude Code 작업을 팀에 넘길 때 필요한 증거, 권한 규칙, 롤백, 무료 PDF, Gumroad, 상담 경로 체크리스트.