Guider/Infra/InfraDevGuide0005
Infra#05· 48분 읽기

InfraDevGuide0005

Docker & 컨테이너 완전 정복

list목차(49)
INFRA DEV GUIDE SERIES · 5단계
🐳 Docker & 컨테이너 완전 정복 A-Z
이미지 · 컨테이너 · Compose · 네트워크 · 볼륨 · 보안 현업 실전
비전공자도 현업에서 바로 쓰는 Docker 완전 마스터 — A부터 Z까지 한 번에!
🎯 대상: 인프라 입문~중급자 ⏱ 학습 기간: 2~3주 ⭐ 난이도: ★★★☆☆ 💻 실습 예제 40+
📚 Infra Dev Guide 시리즈 전체 로드맵
단계 가이드 주제 상태
1단계 InfraDevGuide0001 인프라 개념 완전 정복 (서버·네트워크·스토리지) ✅ 완료
2단계 InfraDevGuide0002 Linux 기초 완전 정복 ✅ 완료
3단계 InfraDevGuide0003 네트워크 기초 완전 정복 ✅ 완료
4단계 InfraDevGuide0004 클라우드 AWS 완전 정복 ✅ 완료
5단계 👉 InfraDevGuide0005 🐳 Docker & 컨테이너 완전 정복 ← 현재 학습 중 🔥 학습 중
6단계 InfraDevGuide0006 CI/CD & 자동화 완전 정복 ⏱ 예정
7단계 InfraDevGuide0007 실전 프로젝트 & 취업 전략 ⏱ 예정
📋 전체 학습 목차 (12 Chapters)
Ch 챕터명 핵심 내용 난이도
01 Docker란? — 컨테이너 혁명 VM vs 컨테이너, Docker 설치, 핵심 개념 ★☆☆☆☆
02 Docker 이미지 완전 정복 Dockerfile, 레이어, 빌드 최적화 ★★☆☆☆
03 컨테이너 실행 & 관리 run/stop/rm, 로그, exec, 포트 매핑 ★★☆☆☆
04 볼륨(Volume) 데이터 영속성 Named Volume, Bind Mount, DB 데이터 보존 ★★☆☆☆
05 네트워크 완전 정복 bridge/host/overlay, 컨테이너 간 통신 ★★★☆☆
06 Docker Compose 완전 정복 멀티 컨테이너, 환경변수, 의존성 ★★★☆☆
07 Dockerfile 고급 & 이미지 최적화 Multi-stage, .dockerignore, 경량화 ★★★☆☆
08 Docker 보안 완전 정복 비root 실행, Secrets, 취약점 스캔 ★★★★☆
09 레지스트리 & 이미지 관리 Docker Hub, ECR, 이미지 태깅 전략 ★★★☆☆
10 모니터링 & 트러블슈팅 stats, 로그 수집, cAdvisor, 장애 대응 ★★★★☆
11 쿠버네티스(K8s) 입문 Docker→K8s, Pod/Deployment/Service ★★★★☆
12 현업 면접 Q&A TOP 12 Docker 면접 핵심 질문 & 완벽 답변 ★★★★☆
🐳 Chapter 01 — Docker란? 컨테이너 혁명의 시작
VM vs 컨테이너 | Docker 설치 | 핵심 3대 개념 | 왜 현업에서 필수인가?

🏠 쉬운 비유: Docker는 도시락통입니다. 밥+반찬+양념을 다 담아두면 집에서 먹든 회사에서 먹든 동일한 맛이 납니다. "내 PC에서는 되는데 서버에서 안 돼요" 문제가 사라집니다!

📊 VM vs Docker 컨테이너 — 핵심 차이
비교 항목 🖥️ 가상머신 🐳 Docker
OS 포함 여부 전체 OS 포함 (수GB) Host OS 공유 (수MB)
시작 속도 수 분 수 초 이내
이식성 낮음 매우 높음 (어디서나 동일)
리소스 효율 낮음 높음 (경량)
💻 Docker 설치 (Ubuntu 22.04)
# Docker 공식 설치 스크립트 (가장 빠른 방법)
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    
    # 현재 사용자를 docker 그룹에 추가 (sudo 없이 사용)
    sudo usermod -aG docker $USER
    newgrp docker
    
    # 설치 확인
    docker --version        # Docker version 26.x.x
    docker compose version  # Docker Compose version v2.x.x
    docker run hello-world  # 첫 컨테이너 실행 테스트
🏗️ Docker 핵심 3대 개념
📦
이미지 (Image)

컨테이너의 설계도. 읽기 전용 레이어 스택. docker build로 생성. Docker Hub에서 공유.

🏃
컨테이너 (Container)

이미지의 실행 인스턴스. 격리된 프로세스. docker run으로 생성. 여러 개 동시 실행 가능.

🏪
레지스트리 (Registry)

이미지 저장·배포 저장소. Docker Hub, AWS ECR, GitHub Container Registry.

📦 Chapter 02 — Docker 이미지 완전 정복
Dockerfile 작성법 | 레이어 구조 | 빌드 최적화 | 베이스 이미지 선택 전략
💻 Dockerfile 핵심 명령어 완전 가이드 (Node.js 실전 예시)
# FROM: 베이스 이미지 지정 (항상 첫 번째!)
    FROM node:20-alpine
    
    # LABEL: 이미지 메타데이터 (관리 목적)
    LABEL maintainer="devops@company.com" version="1.0.0"
    
    # ENV: 환경변수 설정 (컨테이너 실행 중에도 유지)
    ENV NODE_ENV=production PORT=3000 APP_DIR=/app
    
    # WORKDIR: 작업 디렉토리 설정
    WORKDIR $APP_DIR
    
    # COPY: 캐시 최적화 - package.json 먼저 복사!
    COPY package*.json ./
    
    # RUN: 이미지 빌드 시 명령 실행
    RUN npm ci --only=production && npm cache clean --force
    
    # 소스코드 복사 (의존성 설치 후에!)
    COPY . .
    
    # EXPOSE: 포트 문서화
    EXPOSE 3000
    
    # HEALTHCHECK: 컨테이너 상태 확인
    HEALTHCHECK --interval=30s --timeout=3s --retries=3   CMD wget -qO- http://localhost:3000/health || exit 1
    
    # USER: 비root 사용자 실행 (보안 필수!)
    RUN addgroup -S appgroup && adduser -S appuser -G appgroup
    USER appuser
    
    # CMD: 컨테이너 시작 명령
    CMD ["node", "server.js"]
💻 이미지 레이어 캐시 최적화 원칙
# 레이어 구조 시각화
    [ Layer 7 ] COPY . . 소스 변경 여기부터 재빌드
    [ Layer 6 ] RUN npm ci package.json 변경 재빌드
    [ Layer 5 ] COPY package*.json ./ 자주 변함 캐시 재사용!
    [ Layer 4 ] ENV NODE_ENV=... 거의 변함
    [ Layer 3 ] WORKDIR /app
    [ Layer 2 ] RUN adduser ...
    [ Layer 1 ] FROM node:20-alpine 항상 캐시 재사용
    
    # 핵심 원칙: 자주 변하는 레이어는 아래에, 안 변하는 것은 위에!
    # → 소스코드가 바뀌어도 npm install 캐시는 재사용 가능!
    
    # 이미지 빌드
    docker build -t my-app:1.0.0 .
    docker build -t my-app:dev -f Dockerfile.dev .
    docker build --no-cache -t my-app:latest .  # 캐시 무시
    
    # 이미지 관리
    docker images
    docker image prune -a   # 미사용 이미지 정리
    docker history my-app:1.0.0  # 레이어 히스토리
📊 베이스 이미지 선택 가이드
베이스 이미지 크기 특징 추천 용도
ubuntu:22.04 ~77MB 풀 패키지, apt 지원 범용, 복잡한 앱
alpine:3.19 🏆 ~5MB 초경량, apk 패키지 프로덕션 최적 🏅
node:20-alpine ~135MB Node.js 포함 Alpine Node.js 앱
scratch 0MB 완전 빈 이미지 Go 정적 바이너리
🏃 Chapter 03 — 컨테이너 실행 & 관리 완전 정복
docker run 옵션 | 생명주기 관리 | 로그 분석 | 리소스 제한 | 재시작 정책
💻 docker run 전체 옵션 가이드
docker run   -d                            # 백그라운드 실행
      -it                           # 인터랙티브 TTY
      --name my-container           # 컨테이너 이름
      -p 8080:80                    # 포트 매핑 (호스트:컨테이너)
      -v my-volume:/data            # Named Volume 마운트
      -v $(pwd):/app                # Bind Mount
      -e NODE_ENV=production        # 환경변수
      --env-file .env               # .env 파일 환경변수
      --network my-network          # 네트워크 연결
      --restart unless-stopped      # 재시작 정책 (현업 권장)
      --memory 512m                 # 메모리 제한
      --cpus 0.5                    # CPU 제한
      --read-only                   # 파일시스템 읽기 전용 (보안)
      --user 1001:1001              # 실행 사용자 (보안)
      --rm                          # 종료 시 자동 삭제
      --log-opt max-size=10m        # 로그 최대 크기
      --log-opt max-file=3          # 로그 파일 최대 수
      nginx:alpine
💻 컨테이너 모니터링 & 디버깅
# 컨테이너 목록
    docker ps                      # 실행 중만
    docker ps -a                   # 전체 (중지 포함)
    
    # 로그 확인
    docker logs my-container           # 전체 로그
    docker logs -f my-container        # 실시간 로그 (tail -f)
    docker logs --tail 100 my-container # 최근 100줄
    docker logs --since 1h my-container # 1시간 이내
    
    # 내부 접속 (현업 필수 디버깅!)
    docker exec -it my-container /bin/sh    # Alpine
    docker exec -it my-container /bin/bash  # Ubuntu
    docker exec -it my-container env        # 환경변수 확인
    
    # 상세 정보 & 리소스
    docker inspect my-container
    docker stats                          # 실시간 리소스
    docker cp my-container:/app/error.log ./  # 파일 복사
🔄 재시작 정책 비교
정책 동작 사용 상황
no 자동 재시작 안 함 개발/테스트
always 항상 재시작 중요 서비스
unless-stopped 🏅 수동 중지 제외하고 항상 재시작 현업 권장
on-failure[:3] 비정상 종료 시만 (최대 3회) 배치 작업
💾 Chapter 04 — 볼륨(Volume) 데이터 영속성 완전 정복
Named Volume | Bind Mount | DB 데이터 보존 | 백업 & 복구

💡 왜 볼륨이 필요한가? 컨테이너를 삭제하면 내부 데이터도 사라집니다. DB 데이터, 업로드 파일을 영구 보존하려면 볼륨이 반드시 필요합니다.

종류 저장 위치 용도 추천
Named Volume 🏅 /var/lib/docker/volumes/ DB 데이터, 앱 데이터 ✅ 권장
Bind Mount 호스트 지정 경로 개발 시 소스코드 동기화 개발용
tmpfs RAM (재시작 시 삭제) 임시 민감 데이터 특수 상황
💻 볼륨 실전 사용법
# Named Volume - MySQL DB 데이터 보존
    docker volume create mysql-data
    docker run -d   --name mysql   -e MYSQL_ROOT_PASSWORD=secret   -v mysql-data:/var/lib/mysql   --restart unless-stopped   mysql:8.0
    docker volume inspect mysql-data   # 볼륨 정보 확인
    
    # Bind Mount - 개발 환경 소스코드 동기화
    docker run -d   --name dev-node   -p 3000:3000   -v $(pwd):/app            # 현재 디렉토리 동기화
      -v /app/node_modules      # node_modules 보호
      node:20-alpine   sh -c "npm install && npm run dev"
    
    # 볼륨 백업
    docker run --rm   -v mysql-data:/backup-source   -v $(pwd):/backup   alpine tar czf /backup/mysql-$(date +%Y%m%d).tar.gz -C /backup-source .
    
    # 볼륨 정리
    docker volume prune  # 미사용 볼륨 삭제
🌐 Chapter 05 — Docker 네트워크 완전 정복
bridge·host·none·overlay | 컨테이너 간 통신 | 커스텀 네트워크 | DNS 자동 해석
드라이버 격리 특징 사용 상황
bridge 🏅 컨테이너 격리 기본값, 가상 LAN, 포트 매핑 필요 단일 호스트 (현업 기본)
host 없음 호스트 네트워크 직접 사용 성능 중요한 네트워크 앱
none 완전 격리 네트워크 없음 보안 격리, 배치 작업
overlay 멀티 호스트 여러 서버 간 컨테이너 통신 분산 환경 (K8s)
💻 커스텀 네트워크 & 컨테이너 간 DNS 통신
# 커스텀 브리지 네트워크를 써야 하는 이유:
    # 1. 컨테이너 이름으로 DNS 자동 해석! (IP 직접 지정 불필요)
    # 2. 네트워크 격리로 보안 향상
    # 3. 기본 bridge는 컨테이너명 DNS 해석 불가!
    
    docker network create app-network
    
    # 컨테이너를 커스텀 네트워크에 연결
    docker run -d --name backend --network app-network my-backend:1.0
    docker run -d --name db --network app-network postgres:15
    
    # ✨ 핵심: 같은 네트워크 = 이름으로 통신!
    docker exec backend ping db               # 이름으로 핑!
    docker exec backend curl http://db:5432   # 이름으로 연결!
    
    docker network ls
    docker network inspect app-network
    docker network connect app-network other-container
🎼 Chapter 06 — Docker Compose 완전 정복
멀티 컨테이너 오케스트레이션 | docker-compose.yml | 환경변수 | 의존성 | 실전 스택

💡 Docker Compose란? 웹+DB+캐시+Nginx를 하나의 YAML 파일로 정의하고 docker compose up -d 한 번으로 전체 스택을 올리는 도구입니다!

💻 프로덕션 수준 docker-compose.yml
version: "3.8"
    services:
      nginx:
        image: nginx:alpine
        ports: ["80:80","443:443"]
        volumes:
          - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
        depends_on:
          app: { condition: service_healthy }
        restart: unless-stopped
        networks: [frontend]
    
      app:
        build: { context: ., dockerfile: Dockerfile.prod }
        expose: ["3000"]
        environment:
          NODE_ENV: production
          DB_HOST: db       # 서비스명 = DNS! IP 불필요
        env_file: [.env]
        depends_on:
          db: { condition: service_healthy }
        healthcheck:
          test: ["CMD","wget","-qO-","http://localhost:3000/health"]
          interval: 30s
          timeout: 5s
          retries: 3
        restart: unless-stopped
        networks: [frontend, backend]
        deploy:
          resources:
            limits: { cpus: '1.0', memory: 512M }
    
      db:
        image: postgres:15-alpine
        environment:
          POSTGRES_DB: myapp
          POSTGRES_USER: appuser
          POSTGRES_PASSWORD: supersecret
        volumes:
          - postgres-data:/var/lib/postgresql/data
        healthcheck:
          test: ["CMD-SHELL","pg_isready -U appuser"]
          interval: 10s
          retries: 5
        restart: unless-stopped
        networks: [backend]
    
      redis:
        image: redis:7-alpine
        command: redis-server --appendonly yes
        volumes: [redis-data:/data]
        restart: unless-stopped
        networks: [backend]
    
    volumes:
      postgres-data:
      redis-data:
    
    networks:
      frontend: { driver: bridge }
      backend:
        driver: bridge
        internal: true   # ← 외부 인터넷 차단! DB 보안의 핵심
💻 Docker Compose 핵심 명령어
docker compose up -d             # 백그라운드 전체 시작
    docker compose up -d --build     # 이미지 재빌드 후 시작
    docker compose down              # 전체 중지 & 삭제
    docker compose down -v           # 볼륨까지 삭제 (초기화)
    docker compose ps                # 서비스 상태
    docker compose logs -f           # 전체 로그 실시간
    docker compose logs -f app       # 특정 서비스 로그
    docker compose exec app sh       # 컨테이너 접속
    docker compose up -d --scale app=3   # 3개로 수평 확장

🏗️ Chapter 07. Dockerfile 고급 & Multi-stage Build

이미지 크기를 줄이고 빌드 속도를 높이는 프로덕션 필수 기술

🎯 Multi-stage Build란?

하나의 Dockerfile 안에서 여러 빌드 단계(stage)를 정의하여, 최종 이미지에는 실행에 필요한 파일만 포함시키는 기법입니다.

구분 일반 빌드 Multi-stage 빌드
이미지 크기 크다 (빌드도구 포함) 작다 (실행파일만)
보안 소스코드/도구 노출 최소한의 파일만
대표 예시 node:18 (1.1GB) node:18-alpine (50MB)

📝 Go 언어 Multi-stage 예시

# === Stage 1: 빌드 환경 ===
    FROM golang:1.21-alpine AS builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download
    COPY . .
    RUN CGO_ENABLED=0 GOOS=linux go build -o main .
    
    # === Stage 2: 실행 환경 (최소화) ===
    FROM scratch          # 완전히 빈 이미지
    COPY --from=builder /app/main /main
    EXPOSE 8080
    ENTRYPOINT ["/main"]
    # 결과: 빌드이미지 ~400MB → 실행이미지 ~10MB

📝 Node.js Multi-stage 예시

# === Stage 1: 의존성 설치 ===
    FROM node:18-alpine AS deps
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci --only=production
    
    # === Stage 2: 빌드 ===
    FROM node:18-alpine AS builder
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
    # === Stage 3: 실행 환경 ===
    FROM node:18-alpine AS runner
    WORKDIR /app
    ENV NODE_ENV=production
    COPY --from=deps /app/node_modules ./node_modules
    COPY --from=builder /app/dist ./dist
    COPY --from=builder /app/package.json ./
    EXPOSE 3000
    CMD ["node", "dist/server.js"]

⚡ Dockerfile 최적화 10가지 원칙

1. 레이어 순서 최적화
변경 빈도가 낮은 레이어(의존성)를 먼저, 자주 바뀌는 소스코드를 나중에 COPY
2. .dockerignore 사용
node_modules, .git, *.log, dist 등 불필요한 파일 빌드 컨텍스트 제외
3. alpine 이미지 사용
ubuntu(72MB) → alpine(5MB). 단, musl libc 호환성 확인 필요
4. RUN 명령어 병합
RUN apt-get update && apt-get install -y pkg && rm -rf /var/lib/apt/lists/*
5. 특정 버전 태그 사용
FROM node:18.19.0-alpine3.19 (latest 금지 - 재현 불가 빌드 방지)
6. COPY vs ADD
ADD는 URL 다운로드/압축해제 가능하나, 단순 복사는 항상 COPY 사용
7. HEALTHCHECK 추가
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1
8. 비root 유저 실행
RUN adduser -D appuser && chown -R appuser /app; USER appuser
9. ARG와 ENV 구분
ARG: 빌드 시점 변수(이미지에 저장 안됨), ENV: 런타임 환경변수
10. BuildKit 사용
DOCKER_BUILDKIT=1 docker build . (병렬빌드, 캐시 마운트, 시크릿 마운트)

🔧 BuildKit 고급 기능

# syntax=docker/dockerfile:1
    
    # 캐시 마운트 - npm 패키지를 빌드 간 캐시 유지
    FROM node:18-alpine
    RUN --mount=type=cache,target=/root/.npm     npm ci
    
    # 시크릿 마운트 - 이미지에 남기지 않고 빌드 시 접근
    RUN --mount=type=secret,id=mytoken     cat /run/secrets/mytoken | pip install --extra-index-url ...
    
    # 빌드 시 사용:
    # echo "mytoken=abc123" | docker build --secret id=mytoken,- .
    
    # 바인드 마운트 - 소스를 COPY 없이 읽기 전용 마운트
    RUN --mount=type=bind,source=.,target=/src     ls /src

🔒 Chapter 08. Docker 보안 완전 정복

컨테이너 보안은 선택이 아닌 필수 - 현업에서 반드시 적용해야 하는 보안 실천법

⚠️ 컨테이너 보안 위협 TOP 5

위협 설명 대응 방법
취약한 베이스 이미지 CVE 취약점 포함 이미지 사용 Trivy/Snyk 스캔 자동화
root 실행 컨테이너 탈출 시 호스트 권한 획득 USER 비root 계정 지정
시크릿 노출 이미지 레이어에 패스워드/키 포함 Docker Secrets / Vault
과도한 권한 불필요한 Linux 캐퍼빌리티 --cap-drop ALL --cap-add 최소
읽기/쓰기 파일시스템 공격자가 컨테이너 내 파일 변조 --read-only 플래그

🛡️ 1. 비root 사용자 실행

# Dockerfile 내 비root 사용자 생성
    FROM node:18-alpine
    
    # 전용 그룹/사용자 생성
    RUN addgroup -S appgroup && adduser -S appuser -G appgroup
    
    WORKDIR /app
    COPY --chown=appuser:appgroup . .
    RUN npm ci --only=production
    
    # root 대신 appuser로 전환
    USER appuser
    EXPOSE 3000
    CMD ["node", "server.js"]
    
    # 실행 시 확인
    # docker run myapp whoami  → appuser (UID 1001 등)
    # docker run --user 1001:1001 myapp  # UID 직접 지정

🔑 2. Docker Secrets (Swarm 모드)

# 시크릿 생성 (암호화된 Raft 스토어에 저장)
    echo "super_secret_password" | docker secret create db_password -
    
    # 서비스에 시크릿 마운트
    docker service create   --name myapp   --secret db_password   myapp:latest
    # 컨테이너 내: /run/secrets/db_password 파일로 접근
    
    # Docker Compose에서 시크릿 사용 (Compose v3.1+)
    # compose.yml 예시:
    # secrets:
    #   db_password:
    #     external: true
    # services:
    #   app:
    #     secrets:
    #       - db_password
    #     environment:
    #       - DB_PASSWORD_FILE=/run/secrets/db_password

🔍 3. 이미지 취약점 스캔 (Trivy)

# Trivy 설치 (macOS)
    brew install trivy
    
    # 이미지 스캔
    trivy image nginx:latest
    trivy image --severity HIGH,CRITICAL myapp:latest
    
    # 파일시스템 스캔
    trivy fs /path/to/project
    
    # CI/CD 파이프라인 통합 (GitHub Actions)
    # - name: Scan image
    #   uses: aquasecurity/trivy-action@master
    #   with:
    #     image-ref: myapp:latest
    #     exit-code: '1'          # 취약점 발견 시 빌드 실패
    #     severity: 'CRITICAL'
    
    # Docker Scout (Docker 공식)
    docker scout cves myapp:latest
    docker scout recommendations myapp:latest

🔐 4. 런타임 보안 강화

# 읽기전용 파일시스템 (중요!)
    docker run --read-only   --tmpfs /tmp   --tmpfs /run   myapp:latest
    
    # 리소스 제한 (DoS 방지)
    docker run   --memory="512m"   --memory-swap="1g"   --cpus="0.5"   --pids-limit=100   myapp:latest
    
    # 불필요한 캐퍼빌리티 제거
    docker run   --cap-drop ALL   --cap-add NET_BIND_SERVICE   --security-opt no-new-privileges:true   myapp:latest
    
    # seccomp 프로파일 적용
    docker run --security-opt seccomp=default.json myapp:latest
    
    # AppArmor 프로파일
    docker run --security-opt apparmor=docker-default myapp:latest

✅ Docker 보안 체크리스트

  • ☐ 비root 사용자로 컨테이너 실행 (USER 지정)
  • ☐ --read-only 파일시스템 적용
  • ☐ 최신 베이스 이미지 사용 + 정기 스캔
  • ☐ ENV에 패스워드/키 직접 입력 금지
  • ☐ --cap-drop ALL 후 필요한 것만 추가
  • ☐ 메모리/CPU 리소스 제한 설정
  • ☐ Docker daemon TLS 인증 활성화
  • ☐ 프라이빗 레지스트리 접근 제어

📦 Chapter 09. 컨테이너 레지스트리 & 이미지 관리 전략

이미지를 어디에, 어떻게 저장하고 배포할 것인가 - 현업 레지스트리 완전 가이드

🌐 주요 컨테이너 레지스트리 비교

레지스트리 특징 무료 플랜 추천 용도
Docker Hub 가장 대중적, 공식 이미지 제공 퍼블릭 무제한 오픈소스 프로젝트
AWS ECR IAM 연동, EKS/ECS 네이티브 통합 500MB/월 프리티어 AWS 기반 서비스
GCR / Artifact Registry GKE 최적화, 자동 취약점 스캔 0.5GB/월 GCP 기반 서비스
GHCR (GitHub) GitHub Actions와 완벽 통합 퍼블릭 무료 CI/CD 파이프라인
Harbor (self-hosted) 온프레미스, RBAC, 복제 지원 무료 (오픈소스) 기업 내부 레지스트리

🏷️ 이미지 태깅 전략 (Semantic Versioning)

# 버전 태그 (불변 - 프로덕션 필수)
    docker tag myapp:local myregistry.io/team/myapp:1.2.3
    docker tag myapp:local myregistry.io/team/myapp:1.2
    docker tag myapp:local myregistry.io/team/myapp:1
    
    # 환경별 태그
    docker tag myapp:1.2.3 myregistry.io/team/myapp:1.2.3-prod
    docker tag myapp:1.2.3 myregistry.io/team/myapp:1.2.3-staging
    
    # Git 커밋 해시 태그 (CI/CD에서 자동화)
    GIT_SHA=$(git rev-parse --short HEAD)
    docker tag myapp:local myregistry.io/team/myapp:$GIT_SHA
    
    # latest 태그는 dev 환경에서만, 프로덕션 사용 금지!
    
    # 멀티 아키텍처 빌드 (x86 + ARM)
    docker buildx build --platform linux/amd64,linux/arm64 -t myregistry.io/team/myapp:1.2.3 --push .

🔧 AWS ECR 실전 사용법

# 1. ECR 레지스트리 인증 (12시간 유효)
    ECR_URL=123456789012.dkr.ecr.ap-northeast-2.amazonaws.com
    
    aws ecr get-login-password --region ap-northeast-2 \
      | docker login --username AWS --password-stdin $ECR_URL
    
    # 2. 레포지토리 생성 (푸시 시 자동 스캔 활성화)
    aws ecr create-repository \
      --repository-name myapp \
      --image-scanning-configuration scanOnPush=true
    
    # 3. 이미지 빌드 및 푸시
    docker build -t myapp:1.0.0 .
    docker tag myapp:1.0.0 $ECR_URL/myapp:1.0.0
    docker push $ECR_URL/myapp:1.0.0
    
    # 4. 이미지 라이프사이클 정책
    # 최신 10개만 유지, 30일 이상 된 태그 없는 이미지 자동 삭제
    aws ecr put-lifecycle-policy --repository-name myapp \
      --lifecycle-policy-text file://lifecycle-policy.json

🔄 GitHub Actions + GHCR 자동 배포

# .github/workflows/docker-publish.yml
    name: Docker Build and Push
    on:
      push:
        branches: [main]
        tags: ['v*']
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          
          - name: Log in to GHCR
            uses: docker/login-action@v3
            with:
              registry: ghcr.io
              username: GITHUB_ACTOR
              password: GITHUB_TOKEN_SECRET
          
          - name: Extract metadata
            id: meta
            uses: docker/metadata-action@v5
            with:
              images: ghcr.io/myorg/myapp
              tags: |
                type=sha
                type=semver,pattern={{version}}
          
          - name: Build and push
            uses: docker/build-push-action@v5
            with:
              context: .
              push: true
              tags: ghcr.io/myorg/myapp:latest
              cache-from: type=gha
              cache-to: type=gha,mode=max

📊 Chapter 10. 모니터링 & 트러블슈팅 완전 정복

컨테이너 운영의 핵심 - 장애를 사전에 감지하고 빠르게 해결하는 법

📊 컨테이너 모니터링 스택 (Full Observability)

도구 역할 수집 대상
cAdvisor 컨테이너 메트릭 수집기 CPU, 메모리, 네트워크, 디스크I/O
Prometheus 시계열 메트릭 저장소 모든 서비스 메트릭 스크래핑
Grafana 시각화 대시보드 Prometheus 데이터 시각화
Loki 로그 수집/저장 컨테이너 stdout/stderr 로그
Jaeger / Zipkin 분산 추적 (Tracing) 마이크로서비스 요청 흐름 추적

📋 Prometheus + Grafana + cAdvisor 스택 설치

# monitoring/compose.yml
    services:
      prometheus:
        image: prom/prometheus:v2.49.0
        volumes:
          - ./prometheus.yml:/etc/prometheus/prometheus.yml
          - prometheus-data:/prometheus
        ports: ["9090:9090"]
        command:
          - --config.file=/etc/prometheus/prometheus.yml
          - --storage.tsdb.retention.time=15d
    
      grafana:
        image: grafana/grafana:10.3.0
        volumes:
          - grafana-data:/var/lib/grafana
        ports: ["3000:3000"]
        environment:
          - GF_SECURITY_ADMIN_PASSWORD=admin123
        depends_on: [prometheus]
    
      cadvisor:
        image: gcr.io/cadvisor/cadvisor:v0.47.0
        volumes:
          - /:/rootfs:ro
          - /var/run:/var/run:ro
          - /sys:/sys:ro
          - /var/lib/docker/:/var/lib/docker:ro
        ports: ["8080:8080"]
        privileged: true
    
    volumes:
      prometheus-data:
      grafana-data:
# prometheus.yml - 스크래핑 설정
    global:
      scrape_interval: 15s
      evaluation_interval: 15s
    
    scrape_configs:
      - job_name: cadvisor
        static_configs:
          - targets: ['cadvisor:8080']
      
      - job_name: prometheus
        static_configs:
          - targets: ['localhost:9090']
      
      - job_name: myapp
        static_configs:
          - targets: ['myapp:8080']
        metrics_path: /metrics
    
    # Grafana 대시보드 ID:
    # 193  - Docker 컨테이너 모니터링
    # 1860 - Node Exporter Full
    # 11074 - cAdvisor exporter

🚨 실전 트러블슈팅 가이드

컨테이너가 자꾸 재시작될 때
docker logs --tail 50 컨테이너명
docker inspect 컨테이너명 | grep -A 5 State
OOM(메모리 부족) 에러
docker stats 컨테이너명
--memory 옵션으로 메모리 제한 설정
네트워크 연결 불가
docker network inspect 네트워크명
컨테이너명으로 DNS 해석 확인
볼륨 권한 문제
ls -la /var/lib/docker/volumes/
chown -R 1000:1000 /data

🔧 핵심 디버깅 명령어 모음

# === 컨테이너 상태 진단 ===
    docker stats                         # 실시간 리소스 사용량
    docker stats --no-stream             # 1회 스냅샷
    docker top 컨테이너명                # 컨테이너 내 프로세스
    docker inspect 컨테이너명            # 모든 설정/상태 JSON
    
    # === 로그 분석 ===
    docker logs 컨테이너명               # 전체 로그
    docker logs -f --tail 100 컨테이너명 # 마지막 100줄 + 실시간
    docker logs --since 5m 컨테이너명    # 최근 5분 로그
    docker logs 컨테이너명 2>&1 | grep ERROR  # 에러만 필터
    
    # === 컨테이너 내부 접속 및 진단 ===
    docker exec -it 컨테이너명 sh        # 쉘 접속
    docker exec 컨테이너명 ps aux        # 프로세스 목록
    docker exec 컨테이너명 netstat -tlnp # 포트 확인
    docker exec 컨테이너명 cat /etc/hosts  # DNS 설정 확인
    docker exec 컨테이너명 curl -sf http://localhost:8080/health
    
    # === 이미지/컨테이너 분석 ===
    docker history 이미지명              # 레이어 히스토리
    docker diff 컨테이너명              # 파일 변경 사항
    dive 이미지명                        # 레이어별 파일 분석 (dive 설치 필요)
    
    # === 시스템 정리 ===
    docker system df                     # 디스크 사용량
    docker system prune -af              # 모든 미사용 리소스 삭제
    docker image prune --filter "until=48h"  # 48시간 이상 된 이미지

📋 헬스체크 & 자동 복구 설정

# Dockerfile HEALTHCHECK
    HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
      CMD curl -f http://localhost:8080/health || exit 1
    
    # Docker Compose 헬스체크
    services:
      app:
        image: myapp:latest
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
          interval: 30s
          timeout: 10s
          retries: 3
          start_period: 40s
        # depends_on에서 healthcheck 활용
      db:
        image: postgres:16
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U postgres"]
          interval: 10s
          timeout: 5s
          retries: 5
    
    # 자동 재시작 정책
    docker run --restart=on-failure:3 myapp:latest   # 실패 시 최대 3번
    docker run --restart=unless-stopped myapp:latest  # 수동 중지 전까지 재시작
    docker run --restart=always myapp:latest          # 항상 재시작

⎈️ Chapter 11. 쿠버네티스(K8s) 입문 - Docker 다음 단계

Docker를 마스터했다면 이제 K8s로 - 컨테이너 오케스트레이션의 세계

❓ Docker만으로는 왜 부족한가?

문제 Docker만 사용 시 K8s 해결책
스케일링 수동으로 컨테이너 복제 HPA - CPU/메모리 기반 자동 확장
자가 치유 죽은 컨테이너 수동 재시작 죽으면 자동으로 새 Pod 생성
무중단 배포 배포 시 다운타임 발생 Rolling Update / Blue-Green 배포
로드밸런싱 외부 LB 수동 구성 Service가 자동으로 LB 역할
멀티 호스트 단일 서버에 종속 여러 노드에 분산 배치

🏗️ K8s 핵심 아키텍처

┌─────────────────────────────────────────────────────┐
    │                  K8s 클러스터                        │
    │  ┌──────────────────────────────────────────────┐  │
    │  │           Control Plane (마스터 노드)          │  │
    │  │  ┌─────────┐ ┌──────────┐ ┌─────────────┐  │  │
    │  │  │   API   │ │  etcd    │ │  Scheduler  │  │  │
    │  │  │ Server  │ │ (데이터) │ │  (배치결정) │  │  │
    │  │  └─────────┘ └──────────┘ └─────────────┘  │  │
    │  │           ┌───────────────┐                 │  │
    │  │           │   Controller  │                 │  │
    │  │           │   Manager     │                 │  │
    │  │           └───────────────┘                 │  │
    │  └──────────────────────────────────────────────┘  │
    │                                                     │
    │  ┌──────────────┐  ┌──────────────┐                │
    │  │  Worker Node │  │  Worker Node │  ...            │
    │  │ ┌──────────┐ │  │ ┌──────────┐ │                │
    │  │ │  kubelet │ │  │ │  kubelet │ │                │
    │  │ │ kube-    │ │  │ │ kube-    │ │                │
    │  │ │ proxy    │ │  │ │ proxy    │ │                │
    │  │ │┌─┐┌─┐┌─┐│ │  │ │┌─┐┌─┐   │ │                │
    │  │ ││P││P││P││ │  │ ││P││P│   │ │                │
    │  │ ││o││o││o││ │  │ ││o││o│   │ │                │
    │  │ ││d││d││d││ │  │ ││d││d│   │ │                │
    │  │ │└─┘└─┘└─┘│ │  │ │└─┘└─┘   │ │                │
    │  │ └──────────┘ │  │ └──────────┘ │                │
    │  └──────────────┘  └──────────────┘                │
    └─────────────────────────────────────────────────────┘

📋 K8s 핵심 오브젝트 (YAML 예시)

# 1. Deployment - 앱 배포 및 관리
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
      labels:
        app: myapp
    spec:
      replicas: 3              # 3개의 Pod 실행
      selector:
        matchLabels:
          app: myapp
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxSurge: 1          # 배포 중 추가로 생성할 최대 Pod 수
          maxUnavailable: 0    # 배포 중 사용 불가 최소 Pod 수 (0 = 무중단)
      template:
        metadata:
          labels:
            app: myapp
        spec:
          containers:
          - name: myapp
            image: myregistry.io/myapp:1.2.3  # 반드시 버전 태그!
            ports:
            - containerPort: 8080
            resources:
              requests:          # 최소 보장 리소스
                memory: "128Mi"
                cpu: "250m"
              limits:            # 최대 허용 리소스
                memory: "512Mi"
                cpu: "500m"
            livenessProbe:
              httpGet:
                path: /health
                port: 8080
              initialDelaySeconds: 30
              periodSeconds: 10
            readinessProbe:
              httpGet:
                path: /ready
                port: 8080
              initialDelaySeconds: 5
              periodSeconds: 5
# 2. Service - 로드밸런싱 및 서비스 디스커버리
    apiVersion: v1
    kind: Service
    metadata:
      name: myapp-svc
    spec:
      selector:
        app: myapp             # 위 Deployment의 Pod 선택
      ports:
      - port: 80
        targetPort: 8080
      type: ClusterIP          # 클러스터 내부만 접근
      # type: LoadBalancer    # 외부 접근 (클라우드 LB 자동 생성)
      # type: NodePort        # 노드 IP:포트로 외부 접근
    
    ---
    # 3. ConfigMap - 설정 값 분리
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: myapp-config
    data:
      APP_ENV: production
      LOG_LEVEL: info
      DB_HOST: postgres-svc
    
    ---
    # 4. Secret - 민감 정보 저장 (base64 인코딩)
    apiVersion: v1
    kind: Secret
    metadata:
      name: myapp-secret
    type: Opaque
    data:
      DB_PASSWORD: c3VwZXJzZWNyZXQ=  # base64 인코딩 값
      # echo -n "supersecret" | base64

⚡ kubectl 주요 명령어

# === 배포 관리 ===
    kubectl apply -f deployment.yml         # YAML 적용 (생성/수정)
    kubectl delete -f deployment.yml        # YAML 삭제
    kubectl rollout status deployment/myapp # 배포 상태 확인
    kubectl rollout undo deployment/myapp   # 이전 버전으로 롤백
    kubectl scale deployment myapp --replicas=5  # 수동 스케일링
    
    # === 상태 조회 ===
    kubectl get pods -o wide                # Pod 상세 목록
    kubectl get all                         # 모든 리소스
    kubectl describe pod Pod이름            # Pod 상세 정보
    kubectl logs Pod이름 -c 컨테이너명 -f   # 로그 실시간 조회
    
    # === 디버깅 ===
    kubectl exec -it Pod이름 -- sh          # Pod 내부 접속
    kubectl port-forward svc/myapp-svc 8080:80  # 로컬 포트 포워딩
    kubectl get events --sort-by=lastTimestamp  # 이벤트 시간순 조회
    
    # === 컨텍스트 관리 ===
    kubectl config get-contexts             # 사용 가능한 클러스터
    kubectl config use-context 클러스터명  # 클러스터 전환

💡 K8s 학습 로드맵

Docker를 마스터한 후 K8s 학습 순서: minikube 로컬 설치Pod/Deployment/Service 기본ConfigMap/SecretIngress 컨트롤러Helm 패키지 매니저EKS/GKE/AKS 클라우드 관리형 K8s

추천 실습 환경: minikube, kind(Kubernetes in Docker), k3s (경량 K8s)

🎤 Chapter 12. 현업 면접 Q&A TOP 15

DevOps / 인프라 엔지니어 면접에서 실제로 나오는 Docker 질문과 모범 답안

Q1. VM과 컨테이너의 차이점을 설명해주세요.

A: VM은 하이퍼바이저 위에 Guest OS를 포함한 전체 운영체제를 가상화합니다. 부팅에 분~수십초가 걸리고 GB 단위 용량을 사용합니다. 반면 컨테이너는 호스트 OS의 커널을 공유하며 프로세스 수준으로 격리됩니다. 밀리초 단위로 시작하고 MB 단위로 가볍습니다. VM은 강한 격리가 필요한 경우(멀티 테넌트 클라우드), 컨테이너는 빠른 배포와 마이크로서비스에 적합합니다.

Q2. Docker 레이어(Layer) 구조와 Union File System을 설명해주세요.

A: Docker 이미지는 읽기 전용 레이어들의 스택입니다. 각 Dockerfile 명령어(RUN, COPY, ADD)는 새 레이어를 생성합니다. Union File System(OverlayFS)이 여러 레이어를 하나의 파일시스템으로 합쳐서 보여줍니다. 컨테이너 실행 시 최상단에 쓰기 가능한 얇은 레이어가 추가됩니다(Copy-on-Write). 이 구조 덕분에 동일 베이스 이미지를 여러 컨테이너가 공유하여 디스크를 절약합니다. 레이어 캐시 덕분에 빌드도 빠릅니다.

Q3. ENTRYPOINT와 CMD의 차이점은?

A: ENTRYPOINT는 컨테이너가 항상 실행할 기본 명령을 정의하며, docker run 시 재정의하기 어렵습니다. CMD는 ENTRYPOINT에 전달할 기본 인자를 정의하며, docker run 시 쉽게 재정의됩니다. 예를 들어 ENTRYPOINT ["python", "app.py"]를 설정하면 컨테이너는 항상 python app.py를 실행합니다. CMD ["--port", "8080"]을 추가하면 기본 포트를 지정하지만, docker run myapp --port 9090으로 변경 가능합니다. 실행 파일처럼 동작시키려면 ENTRYPOINT, 기본값만 설정하려면 CMD를 사용합니다.

Q4. Docker 네트워크 종류와 각 사용 사례를 설명해주세요.

A: bridge는 기본 네트워크로 같은 호스트 내 컨테이너들이 통신합니다. 사용자 정의 bridge 네트워크에서는 컨테이너명으로 DNS 해석이 됩니다. host는 컨테이너가 호스트 네트워크를 직접 사용합니다. 네트워크 오버헤드가 없어 고성능이지만 포트 충돌 위험이 있습니다. overlay는 여러 호스트에 걸친 컨테이너 통신에 사용됩니다. Docker Swarm과 K8s에서 주로 활용됩니다. none은 네트워크를 완전히 비활성화합니다. 보안이 중요한 배치 작업에 사용됩니다.

Q5. Docker 이미지를 최소화하는 방법들을 말해주세요.

A: 첫째, Multi-stage build를 사용합니다. 빌드 도구는 빌드 스테이지에서만 사용하고 최종 이미지에는 실행 파일만 포함합니다. 둘째, Alpine 기반 이미지를 사용합니다. ubuntu 72MB 대비 alpine은 5MB입니다. 셋째, RUN 명령어를 체이닝하여 레이어 수를 줄이고, 패키지 캐시를 삭제합니다. 넷째, .dockerignore로 빌드 컨텍스트에서 불필요한 파일을 제외합니다. 다섯째, 불필요한 패키지 설치를 피합니다. 여섯째, Go 언어의 경우 scratch 이미지를 기반으로 단일 바이너리를 복사합니다.

Q6. Named Volume과 Bind Mount의 차이점은?

A: Named Volume은 Docker가 관리하는 스토리지입니다. 경로를 지정할 필요 없이 이름만으로 관리하며, 이식성이 좋고 권한 문제가 적습니다. 프로덕션 데이터베이스 등 영속 데이터에 적합합니다. Bind Mount는 호스트의 특정 경로를 컨테이너에 마운트합니다. 호스트 파일시스템과 직접 연동되어 개발 환경에서 코드 핫리로드에 유용합니다. 그러나 호스트 경로에 종속되어 이식성이 낮고 권한 문제가 발생할 수 있습니다.

Q7. 컨테이너 보안을 강화하는 방법을 설명해주세요.

A: 첫째, 비root 사용자로 실행합니다(USER 지정). 둘째, --read-only 플래그로 읽기 전용 파일시스템을 사용합니다. 셋째, --cap-drop ALL로 모든 Linux 캐퍼빌리티를 제거하고 필요한 것만 추가합니다. 넷째, Trivy나 Docker Scout으로 취약점을 정기 스캔합니다. 다섯째, ENV나 ARG에 시크릿을 하드코딩하지 않고 Docker Secrets나 Vault를 사용합니다. 여섯째, 최신 베이스 이미지를 사용합니다. 일곱째, --pids-limit으로 프로세스 수를 제한합니다.

Q8. Docker Compose와 Docker Swarm, Kubernetes의 차이점은?

A: Docker Compose는 단일 호스트에서 여러 컨테이너로 구성된 애플리케이션을 정의하고 실행합니다. 개발/테스트 환경에 주로 사용됩니다. Docker Swarm은 여러 호스트에 걸친 Docker 네이티브 오케스트레이션입니다. 설정이 간단하지만 기능이 K8s보다 제한적입니다. Kubernetes는 가장 강력한 컨테이너 오케스트레이션 플랫폼입니다. 자동 스케일링, 자가 치유, 무중단 배포, 서비스 디스커버리, 시크릿 관리 등을 제공합니다. 복잡하지만 대규모 프로덕션 환경의 표준입니다.

Q9. 컨테이너가 계속 재시작될 때 어떻게 디버깅하나요?

A: 1) docker logs 컨테이너명으로 에러 로그를 확인합니다. 2) docker inspect 컨테이너명으로 종료 코드(ExitCode)와 재시작 횟수를 확인합니다. Exit code 1은 앱 에러, 137은 OOM Kill, 143은 SIGTERM입니다. 3) docker stats로 메모리 사용량이 한계에 가까운지 확인합니다. 4) 헬스체크 설정이 너무 엄격한지 확인합니다. 5) --restart 정책이 재시작을 계속 유발하는지 확인합니다. 6) 필요 시 --entrypoint sh로 진입해 직접 실행해봅니다.

Q10. Docker 이미지 태깅 전략을 어떻게 가져가시겠습니까?

A: 프로덕션에서는 latest 태그를 절대 사용하지 않습니다. Semantic Versioning(1.2.3)을 기본으로 사용하고, Git 커밋 SHA를 함께 태그합니다. 이를 통해 배포된 버전이 정확히 어떤 코드인지 추적 가능합니다. 환경별로 태그를 분리하여(1.2.3-prod, 1.2.3-staging) 환경 간 이미지를 명확히 구분합니다. CI/CD에서는 PR 머지 시 자동으로 빌드하고, 버전 태그를 자동 생성합니다. 오래된 이미지는 라이프사이클 정책으로 자동 정리합니다.

Q11~Q15. 고급 면접 질문

Q11. 컨테이너와 마이크로서비스의 관계를 설명해주세요.

A: 마이크로서비스는 각 서비스를 독립적으로 배포 가능한 작은 단위로 나누는 아키텍처입니다. 컨테이너는 이러한 마이크로서비스를 패키징하고 배포하기에 이상적인 기술입니다. 컨테이너의 격리, 이식성, 빠른 시작이 마이크로서비스의 독립 배포와 확장 요구사항과 완벽하게 맞습니다.

Q12. Docker를 사용한 CI/CD 파이프라인을 설계해주세요.

A: 코드 푸시 → GitHub Actions 트리거 → docker build (Multi-stage) → Trivy로 보안 스캔 → GHCR/ECR에 이미지 푸시 → 태그 기반 버전 관리 → 스테이징 환경 배포 (docker compose / K8s) → 자동화 테스트 → 프로덕션 배포 (Blue-Green 또는 Rolling) → Grafana로 배포 후 모니터링

Q13. 컨테이너에서 로그를 어떻게 관리하나요?

A: 12Factor App 원칙에 따라 컨테이너는 stdout/stderr에만 로그를 출력해야 합니다. Docker는 이를 캡처하여 로그 드라이버(json-file, fluentd, gelf 등)로 전달합니다. 프로덕션에서는 Fluentd나 Filebeat로 로그를 수집하여 ELK 스택(Elasticsearch + Logstash + Kibana)이나 Loki + Grafana에 저장하고 분석합니다.

Q14. Docker의 Copy-on-Write(CoW) 메커니즘을 설명해주세요.

A: 컨테이너가 이미지의 파일을 수정할 때 원본 레이어는 건드리지 않고, 수정할 파일만 컨테이너 레이어로 복사한 후 수정합니다. 이로 인해 같은 이미지에서 여러 컨테이너를 실행해도 각 컨테이너는 독립적인 파일 변경이 가능하고, 이미지 레이어는 공유되어 디스크를 절약합니다.

Q15. 컨테이너에서 상태(state)를 어떻게 관리하나요?

A: 컨테이너 자체는 Stateless(무상태)로 설계하는 것이 원칙입니다. 상태 데이터(DB, 파일 등)는 컨테이너 외부에 분리합니다. 방법으로는 1) Docker Volume을 사용하여 호스트에 영속화, 2) 외부 DB 서비스(RDS 등) 사용, 3) S3 같은 오브젝트 스토리지 사용, 4) Redis 같은 외부 캐시 서버 사용이 있습니다. 이렇게 해야 컨테이너를 언제든지 교체/삭제해도 데이터가 보존됩니다.

✅ Docker 현업 투입 체크리스트

이 모든 항목을 이해하고 실습했다면 현업에서 Docker를 사용할 준비가 되었습니다!

📚 기초 개념 (Ch01-03)

  • ☐ VM vs 컨테이너 차이 설명 가능
  • ☐ Docker 설치 및 Hello World 실행
  • ☐ 이미지와 컨테이너의 관계 이해
  • ☐ Dockerfile 작성 (FROM/RUN/COPY/CMD)
  • ☐ docker build/run/ps/stop/rm 명령어
  • ☐ 포트 바인딩 (-p) 이해 및 사용
  • ☐ 환경변수 (-e) 주입 이해
  • ☐ docker logs / exec 활용

💾 스토리지 & 네트워크 (Ch04-05)

  • ☐ Named Volume으로 DB 데이터 영속화
  • ☐ Bind Mount로 개발 핫리로드 구성
  • ☐ docker volume ls/inspect/rm
  • ☐ 사용자 정의 bridge 네트워크 생성
  • ☐ 컨테이너명으로 DNS 통신 테스트
  • ☐ 네트워크 격리 원리 이해

📋 Compose & 고급 빌드 (Ch06-07)

  • ☐ docker-compose.yml로 웹+DB 스택 구성
  • ☐ depends_on + healthcheck 설정
  • ☐ docker compose up/down/logs
  • ☐ Multi-stage build 적용 경험
  • ☐ .dockerignore 설정
  • ☐ Alpine 기반 이미지로 사이즈 최소화
  • ☐ docker system prune으로 정리

🔒 보안 & 운영 (Ch08-10)

  • ☐ 비root 사용자로 컨테이너 실행
  • ☐ Trivy로 이미지 취약점 스캔
  • ☐ 메모리/CPU 리소스 제한 설정
  • ☐ HEALTHCHECK 설정 경험
  • ☐ ECR 또는 GHCR에 이미지 푸시
  • ☐ Prometheus + Grafana 모니터링 구축
  • ☐ 컨테이너 트러블슈팅 경험 (OOM, 재시작 등)

🎉 Docker & 컨테이너 완전 정복!

이 포스팅을 통해 Docker의 A부터 Z까지 학습을 완료했습니다.
다음 단계로 쿠버네티스(K8s)와 CI/CD 파이프라인 자동화에 도전하세요!

InfraDevGuide0006 예고: CI/CD 파이프라인 완전 정복 (Jenkins, GitHub Actions, ArgoCD)

🗺️ InfraDevGuide 시리즈 전체 로드맵

단계 제목 상태
InfraDevGuide0001 Linux 기초 완전 정복 ✅ 완료
InfraDevGuide0002 네트워킹 기초 ✅ 완료
InfraDevGuide0003 Git & 버전 관리 ✅ 완료
InfraDevGuide0004 Shell Script & 자동화 ✅ 완료
InfraDevGuide0005 Docker & 컨테이너 완전 정복 ← 현재 📖 학습중
InfraDevGuide0006 CI/CD 파이프라인 ⏳ 예정
InfraDevGuide0007 Kubernetes 완전 정복 ⏳ 예정

📝 InfraDevGuide 시리즈 | 인프라 개발자를 위한 완전 정복 가이드

📅 2025 | Docker & 컨테이너 완전 정복 A-Z