spinny:~/writing $ vim docker-containers-complete-guide.md
1~2Docker는 우리가 소프트웨어를 구축, 배포, 실행하는 방식을 바꿔놓았습니다. "내 컴퓨터에서는 작동해"가 아니라, Docker는 여러분의 애플리케이션이 어디서든 동일하게 실행되도록 보장합니다 - 노트북에서, 동료의 컴퓨터에서, CI/CD에서, 그리고 프로덕션에서. 이 가이드에서는 처음부터 실제 애플리케이션 배포까지 다루겠습니다.3~4## Docker란?5~6Docker는 애플리케이션과 모든 종속성을 **컨테이너**라는 표준화된 단위로 패키징하는 플랫폼입니다. 컨테이너는 호스트 OS 커널을 공유하면서도 자체 파일시스템, 네트워크, 프로세스 공간을 가진 격리된 경량 프로세스입니다.7~8```mermaid9graph TD10 subgraph "Traditional Deployment"11 A1[App 1] --> OS1[Guest OS]12 A2[App 2] --> OS2[Guest OS]13 OS1 --> HV[Hypervisor]14 OS2 --> HV15 HV --> HW1[Hardware]16 end17~18 subgraph "Docker Deployment"19 B1[App 1] --> D1[Container]20 B2[App 2] --> D2[Container]21 D1 --> DE[Docker Engine]22 D2 --> DE23 DE --> HW2[Hardware]24 end25```26~27### 컨테이너 vs 가상 머신28~29| 항목 | 컨테이너 | 가상 머신 |30|------|----------|----------|31| **시작** | 초 단위 | 분 단위 |32| **크기** | MB 단위 | GB 단위 |33| **OS** | 호스트 커널 공유 | 전체 게스트 OS |34| **격리** | 프로세스 수준 | 하드웨어 수준 |35| **성능** | 거의 네이티브 | 하이퍼바이저 오버헤드 |36| **밀도** | 호스트당 수백 개 | 호스트당 수십 개 |37~38## Docker 설치39~40```bash41# macOS42brew install --cask docker43~44# Ubuntu/Debian45curl -fsSL https://get.docker.com | sh46sudo usermod -aG docker $USER47~48# Verify installation49docker --version50docker run hello-world51```52~53## 핵심 개념54~55### 이미지56~57이미지는 컨테이너를 생성하기 위한 명령이 담긴 읽기 전용 템플릿입니다. 애플리케이션과 환경의 스냅샷이라고 생각하세요.58~59```bash60# Pull an image from Docker Hub61docker pull node:20-alpine62~63# List local images64docker images65~66# Remove an image67docker rmi node:20-alpine68```69~70### 컨테이너71~72컨테이너는 이미지의 실행 중인 인스턴스입니다. 컨테이너를 생성, 시작, 중지, 삭제할 수 있습니다.73~74```bash75# Run a container76docker run -d --name my-app -p 3000:3000 node:20-alpine77~78# List running containers79docker ps80~81# List all containers (including stopped)82docker ps -a83~84# Stop a container85docker stop my-app86~87# Remove a container88docker rm my-app89~90# View logs91docker logs my-app92~93# Execute a command inside a running container94docker exec -it my-app sh95```96~97## Dockerfile 작성98~99Dockerfile은 이미지를 빌드하기 위한 명령이 담긴 텍스트 파일입니다. 각 명령은 하나의 레이어를 생성합니다.100~101### Node.js 앱을 위한 기본 Dockerfile102~103```dockerfile104# Use an official Node.js runtime as base image105FROM node:20-alpine106~107# Set working directory108WORKDIR /app109~110# Copy package files first (better caching)111COPY package.json package-lock.json ./112~113# Install dependencies114RUN npm ci --only=production115~116# Copy application code117COPY . .118~119# Expose the port the app runs on120EXPOSE 3000121~122# Command to run the application123CMD ["node", "server.js"]124```125~126### 빌드 및 실행127~128```bash129# Build the image130docker build -t my-node-app .131~132# Run the container133docker run -d -p 3000:3000 my-node-app134~135# Visit http://localhost:3000136```137~138## 멀티 스테이지 빌드139~140멀티 스테이지 빌드는 빌드 환경을 런타임에서 분리하여 프로덕션 이미지를 작게 유지합니다.141~142```dockerfile143# Stage 1: Build144FROM node:20-alpine AS builder145WORKDIR /app146COPY package.json package-lock.json ./147RUN npm ci148COPY . .149RUN npm run build150~151# Stage 2: Production152FROM node:20-alpine AS runner153WORKDIR /app154COPY --from=builder /app/dist ./dist155COPY --from=builder /app/node_modules ./node_modules156COPY --from=builder /app/package.json ./157EXPOSE 3000158CMD ["node", "dist/server.js"]159```160~161이렇게 하면 컴파일된 출력과 프로덕션 종속성만 포함된 이미지가 생성됩니다 - 소스 코드 없이, 개발 종속성 없이, 빌드 도구 없이.162~163### Next.js 멀티 스테이지 예제164~165```dockerfile166FROM node:20-alpine AS deps167WORKDIR /app168COPY package.json package-lock.json ./169RUN npm ci170~171FROM node:20-alpine AS builder172WORKDIR /app173COPY --from=deps /app/node_modules ./node_modules174COPY . .175RUN npm run build176~177FROM node:20-alpine AS runner178WORKDIR /app179ENV NODE_ENV=production180COPY --from=builder /app/public ./public181COPY --from=builder /app/.next/standalone ./182COPY --from=builder /app/.next/static ./.next/static183EXPOSE 3000184CMD ["node", "server.js"]185```186~187## 볼륨: 영구 데이터188~189기본적으로 컨테이너 내부의 데이터는 컨테이너가 제거되면 사라집니다. 볼륨이 이 문제를 해결합니다.190~191```bash192# Create a named volume193docker volume create my-data194~195# Run with a volume196docker run -d -v my-data:/app/data my-app197~198# Bind mount (map host directory to container)199docker run -d -v $(pwd)/data:/app/data my-app200~201# List volumes202docker volume ls203```204~205## 네트워킹206~207Docker는 컨테이너가 통신할 수 있도록 격리된 네트워크를 생성합니다.208~209```bash210# Create a custom network211docker network create my-network212~213# Run containers on the same network214docker run -d --name api --network my-network my-api215docker run -d --name db --network my-network postgres:16216~217# Containers can reach each other by name218# From "api" container: postgres://db:5432219```220~221```mermaid222graph LR223 subgraph "my-network"224 API[api container\nport 3000] -- "db:5432" --> DB[db container\nport 5432]225 end226 User -- "localhost:3000" --> API227```228~229## Docker Compose230~231Docker Compose를 사용하면 단일 YAML 파일로 멀티 컨테이너 애플리케이션을 정의하고 실행할 수 있습니다.232~233### docker-compose.yml234~235```yaml236services:237 api:238 build: ./api239 ports:240 - "3000:3000"241 environment:242 - DATABASE_URL=postgres://user:pass@db:5432/mydb243 depends_on:244 - db245~246 db:247 image: postgres:16-alpine248 environment:249 - POSTGRES_USER=user250 - POSTGRES_PASSWORD=pass251 - POSTGRES_DB=mydb252 volumes:253 - pgdata:/var/lib/postgresql/data254 ports:255 - "5432:5432"256~257 redis:258 image: redis:7-alpine259 ports:260 - "6379:6379"261~262volumes:263 pgdata:264```265~266### 명령어267~268```bash269# Start all services270docker compose up -d271~272# View logs273docker compose logs -f274~275# Stop all services276docker compose down277~278# Rebuild and restart279docker compose up -d --build280~281# Scale a service282docker compose up -d --scale api=3283```284~285## .dockerignore286~287`.gitignore`와 마찬가지로, 이 파일은 불필요한 파일이 이미지에 복사되는 것을 방지합니다.288~289```plaintext290node_modules291.git292.env293*.md294.next295dist296coverage297```298~299## 프로덕션 모범 사례300~301### 1. 작은 베이스 이미지 사용302~303```dockerfile304# Bad: 1GB+305FROM node:20306~307# Good: ~180MB308FROM node:20-alpine309```310~311### 2. Root로 실행하지 않기312~313```dockerfile314FROM node:20-alpine315RUN addgroup -S app && adduser -S app -G app316USER app317WORKDIR /home/app318COPY --chown=app:app . .319```320~321### 3. 특정 이미지 태그 사용322~323```dockerfile324# Bad: can change unexpectedly325FROM node:latest326~327# Good: pinned version328FROM node:20.11-alpine3.19329```330~331### 4. 빌드 캐시 활용332~333Dockerfile 명령을 변경 빈도가 낮은 것부터 높은 것 순으로 정렬하세요:334~335```dockerfile336FROM node:20-alpine337WORKDIR /app338~339# These change rarely - cached340COPY package.json package-lock.json ./341RUN npm ci --only=production342~343# This changes often - not cached344COPY . .345```346~347### 5. 헬스 체크348~349```dockerfile350HEALTHCHECK --interval=30s --timeout=3s --retries=3 \351 CMD wget -qO- http://localhost:3000/health || exit 1352```353~354### 6. 환경 변수 사용355~356```dockerfile357ENV NODE_ENV=production358ENV PORT=3000359```360~361## 자주 사용하는 Docker 명령어 치트 시트362~363```bash364# Images365docker build -t name:tag . # Build image366docker images # List images367docker rmi image_name # Remove image368docker image prune # Remove unused images369~370# Containers371docker run -d -p 3000:3000 image # Run detached372docker ps # List running373docker stop container_name # Stop374docker rm container_name # Remove375docker logs -f container_name # Follow logs376docker exec -it container sh # Shell into container377~378# Compose379docker compose up -d # Start services380docker compose down # Stop services381docker compose logs -f # Follow all logs382docker compose ps # List services383~384# Cleanup385docker system prune -a # Remove everything unused386```387~388## Docker에서 Kubernetes로389~390Docker는 개별 컨테이너를 관리합니다. 여러 서버에 걸쳐 수백 개의 컨테이너를 오케스트레이션해야 할 때 Kubernetes가 필요합니다. Docker와 Kubernetes는 상호 보완적입니다:391~3921. **Docker**: 컨테이너를 빌드하고 실행3932. **Kubernetes**: 대규모로 컨테이너를 오케스트레이션 (스케줄링, 스케일링, 자가 복구)394~395다음 단계에 관심이 있다면, Kubernetes 소개에 대한 제 글을 확인해보세요.396~397## 결론398~399Docker는 현대 개발자에게 필수적인 기술입니다. 환경 불일치를 제거하고, 배포를 단순화하며, Kubernetes를 통한 컨테이너 오케스트레이션의 기반입니다. 간단한 Dockerfile로 시작하여, 멀티 서비스 앱에는 Docker Compose로 이동하고, 성장하면서 멀티 스테이지 빌드와 보안 모범 사례를 도입하세요.400~401Docker를 배우는 가장 좋은 방법은 이미 작업 중인 프로젝트를 컨테이너화하는 것입니다. 오늘 시작하세요.402~
NORMAL · docker-containers-complete-guide.md [readonly]402 lines · :q to close