spinny:~/writing $ less docker-containers-complete-guide.md
12Docker는 우리가 소프트웨어를 구축, 배포, 실행하는 방식을 바꿔놓았습니다. "내 컴퓨터에서는 작동해"가 아니라, Docker는 여러분의 애플리케이션이 어디서든 동일하게 실행되도록 보장합니다 - 노트북에서, 동료의 컴퓨터에서, CI/CD에서, 그리고 프로덕션에서. 이 가이드에서는 처음부터 실제 애플리케이션 배포까지 다루겠습니다.34## Docker란?56Docker는 애플리케이션과 모든 종속성을 **컨테이너**라는 표준화된 단위로 패키징하는 플랫폼입니다. 컨테이너는 호스트 OS 커널을 공유하면서도 자체 파일시스템, 네트워크, 프로세스 공간을 가진 격리된 경량 프로세스입니다.78```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 end1718 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```2627### 컨테이너 vs 가상 머신2829| 항목 | 컨테이너 | 가상 머신 |30|------|----------|----------|31| **시작** | 초 단위 | 분 단위 |32| **크기** | MB 단위 | GB 단위 |33| **OS** | 호스트 커널 공유 | 전체 게스트 OS |34| **격리** | 프로세스 수준 | 하드웨어 수준 |35| **성능** | 거의 네이티브 | 하이퍼바이저 오버헤드 |36| **밀도** | 호스트당 수백 개 | 호스트당 수십 개 |3738## Docker 설치3940```bash41# macOS42brew install --cask docker4344# Ubuntu/Debian45curl -fsSL https://get.docker.com | sh46sudo usermod -aG docker $USER4748# Verify installation49docker --version50docker run hello-world51```5253## 핵심 개념5455### 이미지5657이미지는 컨테이너를 생성하기 위한 명령이 담긴 읽기 전용 템플릿입니다. 애플리케이션과 환경의 스냅샷이라고 생각하세요.5859```bash60# Pull an image from Docker Hub61docker pull node:20-alpine6263# List local images64docker images6566# Remove an image67docker rmi node:20-alpine68```6970### 컨테이너7172컨테이너는 이미지의 실행 중인 인스턴스입니다. 컨테이너를 생성, 시작, 중지, 삭제할 수 있습니다.7374```bash75# Run a container76docker run -d --name my-app -p 3000:3000 node:20-alpine7778# List running containers79docker ps8081# List all containers (including stopped)82docker ps -a8384# Stop a container85docker stop my-app8687# Remove a container88docker rm my-app8990# View logs91docker logs my-app9293# Execute a command inside a running container94docker exec -it my-app sh95```9697## Dockerfile 작성9899Dockerfile은 이미지를 빌드하기 위한 명령이 담긴 텍스트 파일입니다. 각 명령은 하나의 레이어를 생성합니다.100101### Node.js 앱을 위한 기본 Dockerfile102103```dockerfile104# Use an official Node.js runtime as base image105FROM node:20-alpine106107# Set working directory108WORKDIR /app109110# Copy package files first (better caching)111COPY package.json package-lock.json ./112113# Install dependencies114RUN npm ci --only=production115116# Copy application code117COPY . .118119# Expose the port the app runs on120EXPOSE 3000121122# Command to run the application123CMD ["node", "server.js"]124```125126### 빌드 및 실행127128```bash129# Build the image130docker build -t my-node-app .131132# Run the container133docker run -d -p 3000:3000 my-node-app134135# Visit http://localhost:3000136```137138## 멀티 스테이지 빌드139140멀티 스테이지 빌드는 빌드 환경을 런타임에서 분리하여 프로덕션 이미지를 작게 유지합니다.141142```dockerfile143# Stage 1: Build144FROM node:20-alpine AS builder145WORKDIR /app146COPY package.json package-lock.json ./147RUN npm ci148COPY . .149RUN npm run build150151# 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```160161이렇게 하면 컴파일된 출력과 프로덕션 종속성만 포함된 이미지가 생성됩니다 - 소스 코드 없이, 개발 종속성 없이, 빌드 도구 없이.162163### Next.js 멀티 스테이지 예제164165```dockerfile166FROM node:20-alpine AS deps167WORKDIR /app168COPY package.json package-lock.json ./169RUN npm ci170171FROM node:20-alpine AS builder172WORKDIR /app173COPY --from=deps /app/node_modules ./node_modules174COPY . .175RUN npm run build176177FROM 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```186187## 볼륨: 영구 데이터188189기본적으로 컨테이너 내부의 데이터는 컨테이너가 제거되면 사라집니다. 볼륨이 이 문제를 해결합니다.190191```bash192# Create a named volume193docker volume create my-data194195# Run with a volume196docker run -d -v my-data:/app/data my-app197198# Bind mount (map host directory to container)199docker run -d -v $(pwd)/data:/app/data my-app200201# List volumes202docker volume ls203```204205## 네트워킹206207Docker는 컨테이너가 통신할 수 있도록 격리된 네트워크를 생성합니다.208209```bash210# Create a custom network211docker network create my-network212213# Run containers on the same network214docker run -d --name api --network my-network my-api215docker run -d --name db --network my-network postgres:16216217# Containers can reach each other by name218# From "api" container: postgres://db:5432219```220221```mermaid222graph LR223 subgraph "my-network"224 API[api container\nport 3000] -- "db:5432" --> DB[db container\nport 5432]225 end226 User -- "localhost:3000" --> API227```228229## Docker Compose230231Docker Compose를 사용하면 단일 YAML 파일로 멀티 컨테이너 애플리케이션을 정의하고 실행할 수 있습니다.232233### docker-compose.yml234235```yaml236services:237 api:238 build: ./api239 ports:240 - "3000:3000"241 environment:242 - DATABASE_URL=postgres://user:pass@db:5432/mydb243 depends_on:244 - db245246 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"256257 redis:258 image: redis:7-alpine259 ports:260 - "6379:6379"261262volumes:263 pgdata:264```265266### 명령어267268```bash269# Start all services270docker compose up -d271272# View logs273docker compose logs -f274275# Stop all services276docker compose down277278# Rebuild and restart279docker compose up -d --build280281# Scale a service282docker compose up -d --scale api=3283```284285## .dockerignore286287`.gitignore`와 마찬가지로, 이 파일은 불필요한 파일이 이미지에 복사되는 것을 방지합니다.288289```plaintext290node_modules291.git292.env293*.md294.next295dist296coverage297```298299## 프로덕션 모범 사례300301### 1. 작은 베이스 이미지 사용302303```dockerfile304# Bad: 1GB+305FROM node:20306307# Good: ~180MB308FROM node:20-alpine309```310311### 2. Root로 실행하지 않기312313```dockerfile314FROM node:20-alpine315RUN addgroup -S app && adduser -S app -G app316USER app317WORKDIR /home/app318COPY --chown=app:app . .319```320321### 3. 특정 이미지 태그 사용322323```dockerfile324# Bad: can change unexpectedly325FROM node:latest326327# Good: pinned version328FROM node:20.11-alpine3.19329```330331### 4. 빌드 캐시 활용332333Dockerfile 명령을 변경 빈도가 낮은 것부터 높은 것 순으로 정렬하세요:334335```dockerfile336FROM node:20-alpine337WORKDIR /app338339# These change rarely - cached340COPY package.json package-lock.json ./341RUN npm ci --only=production342343# This changes often - not cached344COPY . .345```346347### 5. 헬스 체크348349```dockerfile350HEALTHCHECK --interval=30s --timeout=3s --retries=3 \351 CMD wget -qO- http://localhost:3000/health || exit 1352```353354### 6. 환경 변수 사용355356```dockerfile357ENV NODE_ENV=production358ENV PORT=3000359```360361## 자주 사용하는 Docker 명령어 치트 시트362363```bash364# Images365docker build -t name:tag . # Build image366docker images # List images367docker rmi image_name # Remove image368docker image prune # Remove unused images369370# 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 container377378# Compose379docker compose up -d # Start services380docker compose down # Stop services381docker compose logs -f # Follow all logs382docker compose ps # List services383384# Cleanup385docker system prune -a # Remove everything unused386```387388## Docker에서 Kubernetes로389390Docker는 개별 컨테이너를 관리합니다. 여러 서버에 걸쳐 수백 개의 컨테이너를 오케스트레이션해야 할 때 Kubernetes가 필요합니다. Docker와 Kubernetes는 상호 보완적입니다:3913921. **Docker**: 컨테이너를 빌드하고 실행3932. **Kubernetes**: 대규모로 컨테이너를 오케스트레이션 (스케줄링, 스케일링, 자가 복구)394395다음 단계에 관심이 있다면, Kubernetes 소개에 대한 제 글을 확인해보세요.396397## 결론398399Docker는 현대 개발자에게 필수적인 기술입니다. 환경 불일치를 제거하고, 배포를 단순화하며, Kubernetes를 통한 컨테이너 오케스트레이션의 기반입니다. 간단한 Dockerfile로 시작하여, 멀티 서비스 앱에는 Docker Compose로 이동하고, 성장하면서 멀티 스테이지 빌드와 보안 모범 사례를 도입하세요.400401Docker를 배우는 가장 좋은 방법은 이미 작업 중인 프로젝트를 컨테이너화하는 것입니다. 오늘 시작하세요.402
:Docker 초보자 가이드: 첫 이미지부터 프로덕션 배포까지lines 1-402 (END) — press q to close