본문으로 건너뛰기
AIDevOps
  • Learn
  • Learning Paths
  • Practice
  • Open Source
  • Books
  • Engineering

    AI DevOpsAI 서비스 개발·운영 전체 지도LLMOpsLLM 배포·평가·관측실전 프로젝트AI Agent 프로젝트 실습

    Knowledge

    Docs기술 문서 모음Blog엔지니어링 아티클Plogger개발 기록 피드

    Validate

    Certification3단계 역량 인증 · 준비 중
AI Models
LlamaMistralGemmaDeepSeekQwen
🐳 DevOps
DevOps 입문 & 로드맵LinuxDockerCI/CD|Kubernetes 기본K8s 심화/실무PrometheusGrafana
🤖 AI 실전 개발
AI 실전 입문 & 로드맵Hugging FaceLangChainLlamaIndexLLMOps|LangGraphMCPMulti-AgentAgent Evaluation
🧠 AI Core
AI 입문 & 로드맵ML FundamentalsLLM Fundamentals|Python AIC++|PyTorchTensorFlowJAX
🧠 AI Agent 개발
금융 AI AgentLLM API 서버주식 투자 AgentAIOps AI Agent교육 AI Agent코딩 AI Agent
🌱 Spring Cloud
Spring 입문 & 로드맵Spring Cloud GatewaySpring BootJava|Spring AISpring SecuritySpring BatchSpring JPA
🧱 인프라
인프라 입문 & 로드맵NginxRedis
☁️ 클라우드
클라우드 입문 & 로드맵AWSGCPAzureNCPCloudflare
🎨 Frontend
Frontend 입문 & 로드맵JavaScriptTypeScript|ReactNext.js|VueNuxt
📱 Mobile
Mobile 입문 & 로드맵KotlinAndroidFlutter
⚙️ Backend
Backend 입문 & 로드맵Python 기본FastAPIDjangoFlask|CGoGinNode.js
💾 Database
DB 입문 & 로드맵공통 SQLOracleMySQLPostgreSQL|MongoDB벡터 DB
🧪 검증
k6JMeternGrinder
AIDevOps

Engineering AI. From Code to Production.
AI와 AI Agent를 개발하고 운영하기 위한 엔지니어링 학습 플랫폼

Learn

  • 전체 가이드
  • Learning Paths
  • Practice
  • Books

Resources

  • AI DevOps
  • LLMOps
  • 실전 프로젝트
  • Docs
  • Blog
  • Plogger
  • Open Source
  • Certification (준비 중)

Start Here

  • AI Core 로드맵
  • AI 실전 개발 로드맵
  • Spring Cloud 로드맵
  • DevOps 로드맵
  • 인프라 로드맵

 

  • 클라우드 로드맵
  • Frontend 로드맵
  • Mobile 로드맵
  • Backend 로드맵
  • Database 로드맵
© 2026 AI DevOps Korea. All rights reserved.
이용약관개인정보처리방침Sitemaptestforge.kr
  1. Home
  2. Learn
  3. DevOps
  4. Docker
컨테이너 기술 완전 가이드 — BuildKit·Swarm까지

🐳 Docker 완전 가이드

Visitors

컨테이너가 VM과 근본적으로 무엇이 다른지부터, 이미지 레이어 구조, Dockerfile·멀티 스테이지 빌드, BuildKit/buildx 멀티 플랫폼 빌드, 네트워크, 볼륨, Docker Compose, Docker Swarm 오케스트레이션, 컨테이너 보안·취약점 스캔까지 — Kubernetes로 넘어가기 전 반드시 다져야 할 Docker 실무 지식을 정리합니다.

  • Beginner · 입문
  • 업데이트 2026.09.20
  • 약 22분 읽기
  • 18개 섹션
  • 예제 코드 11개
  • 웹 IDE 실습 제공
🐳

Docker 웹 IDE

설치 없이 브라우저에서 코드를 실행하고 단계별 예제로 익혀보세요.

웹 IDE 열기 →
개발 환경 표준화CI/CD 파이프라인 & 멀티 플랫폼 빌드Docker Swarm 오케스트레이션마이크로서비스 패키징

관련 프레임워크 & 개발환경

☸️Kubernetes 기본→☸️K8s 심화/실무→🐧Linux→CICI/CD→

목차

0 / 20
  1. 가이드 사용법
  2. 구조 다이어그램
  3. 컨테이너란 무엇인가
  4. 설치
  5. 기본 명령어와 컨테이너 생명주기
  6. 이미지와 레이어 구조
  7. Dockerfile 작성 & 멀티 스테이지 빌드
  8. BuildKit & buildx — 멀티 플랫폼 빌드
  9. Docker 네트워크
  10. 볼륨과 데이터 영속성
  11. Docker Compose로 다중 컨테이너 구성
  12. Docker Swarm — 아키텍처
  13. Swarm 서비스 배포 & 롤링 업데이트
  14. Docker Stack & Swarm vs Kubernetes
  15. 컨테이너 보안 & 취약점 스캔
  16. 베스트 프랙티스
  17. 다음 단계
  18. Docker 설계
  19. 운영 기준
  20. 검증 전략
목차 20개 섹션
  1. 가이드 사용법
  2. 구조 다이어그램
  3. 컨테이너란 무엇인가
  4. 설치
  5. 기본 명령어와 컨테이너 생명주기
  6. 이미지와 레이어 구조
  7. Dockerfile 작성 & 멀티 스테이지 빌드
  8. BuildKit & buildx — 멀티 플랫폼 빌드
  9. Docker 네트워크
  10. 볼륨과 데이터 영속성
  11. Docker Compose로 다중 컨테이너 구성
  12. Docker Swarm — 아키텍처
  13. Swarm 서비스 배포 & 롤링 업데이트
  14. Docker Stack & Swarm vs Kubernetes
  15. 컨테이너 보안 & 취약점 스캔
  16. 베스트 프랙티스
  17. 다음 단계
  18. Docker 설계
  19. 운영 기준
  20. 검증 전략

가이드 사용법

읽는 방향

Docker를 실무 흐름으로 이해하기

컨테이너가 VM과 근본적으로 무엇이 다른지부터, 이미지 레이어 구조, Dockerfile·멀티 스테이지 빌드, BuildKit/buildx 멀티 플랫폼 빌드, 네트워크, 볼륨, Docker Compose, Docker Swarm 오케스트레이션, 컨테이너 보안·취약점 스캔까지 — Kubernetes로 넘어가기 전 반드시 다져야 할 Docker 실무 지식을 정리합니다. 이 가이드는 개념을 나열하기보다, 실제 프로젝트에서 판단해야 하는 순서대로 내용을 따라갈 수 있게 구성했습니다.

핵심 관점

인프라 / 운영

설치 명령을 외우기보다 트래픽, 런타임, 관측, 장애 대응이 어떤 순서로 이어지는지 파악합니다.

개발 환경 표준화CI/CD 파이프라인 & 멀티 플랫폼 빌드Docker Swarm 오케스트레이션마이크로서비스 패키징

구조 다이어그램

글로 읽은 내용을 머릿속에 오래 남기려면 먼저 흐름을 그림으로 잡는 편이 좋습니다. 아래 두 그림은 Docker를 학습할 때 계속 되돌아볼 수 있는 기준 지도입니다.

학습 흐름

다이어그램 렌더링 중…

아키텍처 관점

다이어그램 렌더링 중…

컨테이너란 무엇인가

Docker를 처음 펼칠 때는 세부 명령보다 큰 그림이 먼저입니다. 이 섹션에서는 앞으로 배울 개념들이 어떤 문제를 풀기 위해 등장했는지부터 잡아봅니다.

컨테이너는 애플리케이션과 그 실행에 필요한 라이브러리·런타임·설정을 하나의 격리된 단위로 묶는 기술입니다. 가상머신(VM)이 하드웨어 자체를 가상화해 게스트 OS 전체를 통째로 띄우는 것과 달리, 컨테이너는 호스트 OS의 커널을 그대로 공유하면서 프로세스 수준에서만 격리됩니다. 그래서 VM은 부팅에 수십 초~수 분이 걸리지만, 컨테이너는 이미 떠 있는 커널 위에서 프로세스 하나를 띄우는 것과 비슷해 1초 안팎으로 시작합니다.
다이어그램 렌더링 중…
비교 항목VMContainer
격리 단위OS 전체 (게스트 OS 포함)프로세스 (커널 공유)
시작 속도수십 초 ~ 수 분1초 안팎
이미지 크기보통 GB 단위보통 MB 단위
밀도서버당 수~수십 개서버당 수십~수백 개

Tip

"컨테이너 = 가벼운 VM"이라는 비유는 절반만 맞습니다. 커널을 공유하기 때문에 완전한 OS 격리가 아니라 프로세스 격리에 가깝고, 그래서 훨씬 가볍지만 커널 취약점은 호스트 전체에 영향을 줄 수 있습니다 — 이 트레이드오프를 뒤의 보안 섹션에서 다룹니다.

설치

여기서는 설치을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

macOS/Windows에서는 Docker Desktop이 Docker Engine, CLI, Compose를 한 번에 설치해줍니다. Linux 서버에는 Docker Desktop 없이 Docker Engine만 직접 설치하는 경우가 많습니다.
BASH
# Docker Desktop (macOS/Windows): https://docker.com/get-started

# Linux — Docker Engine 설치
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER   # sudo 없이 docker 명령 실행 (재로그인 필요)

docker --version
docker info      # 데몬 연결 상태, 스토리지 드라이버 등 확인

Tip

usermod로 docker 그룹에 자신을 추가하면 sudo 없이 docker 명령을 쓸 수 있지만, 이는 사실상 루트 권한을 넘겨주는 것과 같습니다 — 여러 사용자가 접속하는 서버라면 신중하게 부여하세요.

기본 명령어와 컨테이너 생명주기

여기서는 기본 명령어와 컨테이너 생명주기을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

이미지(Image)는 컨테이너를 만들기 위한 읽기 전용 템플릿이고, 컨테이너(Container)는 그 이미지를 실행한 인스턴스입니다. 같은 이미지로 컨테이너를 몇 개든 띄울 수 있고, 컨테이너를 지워도 원본 이미지는 그대로 남습니다.
BASH
docker pull nginx             # 이미지 다운로드
docker run -d -p 80:80 --name web nginx  # 백그라운드 실행 + 이름 지정
docker ps                     # 실행 중인 컨테이너 목록
docker ps -a                  # 종료된 컨테이너까지 전체 목록
docker logs -f web            # 로그 실시간 확인
docker exec -it web bash      # 실행 중인 컨테이너 내부 접속
docker stop web                # 정상 종료 (SIGTERM)
docker rm web                  # 컨테이너 삭제 (정지 상태여야 함)
docker rmi nginx               # 이미지 삭제
명령어역할
docker pull레지스트리(Docker Hub 등)에서 이미지를 내려받음
docker run이미지로부터 컨테이너를 생성하고 시작
docker stop / start실행 중인 컨테이너를 정지 / 정지된 컨테이너를 재시작
docker rm / rmi컨테이너 삭제 / 이미지 삭제

Tip

docker stop은 컨테이너 안의 프로세스에 SIGTERM을 보내고 일정 시간(기본 10초) 기다린 뒤 응답이 없으면 SIGKILL로 강제 종료합니다 — 애플리케이션이 SIGTERM을 받아 안전하게 종료(graceful shutdown)하도록 만들어두면 배포·재시작 시 요청이 끊기는 것을 줄일 수 있습니다.

이미지와 레이어 구조

여기서는 이미지와 레이어 구조을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

Docker 이미지는 Dockerfile의 각 명령어가 하나씩 쌓인 읽기 전용 레이어들의 집합입니다. 같은 레이어가 이미 캐시되어 있으면 Docker는 그 레이어를 다시 만들지 않고 재사용하기 때문에, Dockerfile에서 자주 바뀌는 내용을 뒤쪽에 둘수록 빌드가 빨라집니다.
다이어그램 렌더링 중…

Tip

소스 코드(COPY . .)를 package.json 복사보다 먼저 두면, 코드 한 줄만 바꿔도 그 아래에 있는 npm ci 레이어까지 캐시가 깨져 매번 의존성을 처음부터 다시 설치하게 됩니다 — 변경 빈도가 낮은 명령을 위로, 잦은 명령을 아래로 배치하세요.

Dockerfile 작성 & 멀티 스테이지 빌드

여기서는 Dockerfile 작성 & 멀티 스테이지 빌드을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

멀티 스테이지 빌드는 빌드에만 필요한 도구(컴파일러, devDependencies)와 실제 실행에 필요한 결과물을 서로 다른 스테이지로 분리합니다. 최종 이미지는 마지막 스테이지만 남기 때문에, 빌드 도구가 전혀 포함되지 않은 훨씬 가벼운 이미지를 만들 수 있습니다.
DockerfileDOCKERFILE
# Stage 1: 빌드 전용 — devDependencies와 소스 전체 포함
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: 실행 전용 — 빌드 결과물과 production 의존성만 복사
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
명령어역할
FROM베이스 이미지 지정 (AS로 스테이지 이름 부여 가능)
COPY --from=builder이전 스테이지의 결과물만 선택적으로 복사
RUN이미지 빌드 시점에 한 번 실행 (레이어 생성)
CMD vs ENTRYPOINTCMD는 실행 시 통째로 덮어쓰기 쉬움, ENTRYPOINT는 고정 실행파일 + CMD로 기본 인자만 전달할 때 사용

Tip

최종 스테이지에서 빌드 스테이지의 node_modules를 통째로 복사하면 devDependencies까지 그대로 딸려옵니다 — 위 예시처럼 dist 결과물만 복사하고 production 의존성은 최종 스테이지에서 다시 설치하는 편이 이미지를 더 가볍게 만듭니다.

BuildKit & buildx — 멀티 플랫폼 빌드

여기서는 BuildKit & buildx — 멀티 플랫폼 빌드을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

BuildKit은 Docker 18.09부터 기본으로 내장된 차세대 빌드 엔진으로, Dockerfile의 각 단계를 의존성 그래프로 분석해 관련 없는 단계를 병렬로 실행하고, 캐시를 훨씬 세밀하게(레이어 단위가 아니라 마운트 단위로) 재사용합니다. buildx는 이 BuildKit을 CLI에서 확장해 쓰는 플러그인으로, Apple Silicon Mac에서 만든 이미지를 x86 서버에도 그대로 돌아가게 하는 멀티 플랫폼 빌드가 대표 기능입니다.
다이어그램 렌더링 중…
Dockerfile — 캐시 마운트로 의존성 재설치 방지DOCKERFILE
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
# npm 캐시를 레이어가 아니라 별도 캐시 마운트에 보관 — 이미지 레이어에는 남지 않으면서
# 빌드마다 재사용되어, package.json이 바뀌어도 이미 받은 패키지는 다시 안 받음
RUN --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
CMD ["node", "server.js"]
BASH
# buildx 빌더 생성 & 활성화 (최초 1회)
docker buildx create --name multiarch --use

# 여러 아키텍처를 동시에 빌드해 레지스트리에 바로 push
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myrepo/myapp:1.0.0 \
  --push .

# 원격 캐시를 레지스트리에 저장 — CI 러너가 매번 새로 뜨는 환경에서도 캐시 재사용
docker buildx build \
  --cache-to type=registry,ref=myrepo/myapp:buildcache \
  --cache-from type=registry,ref=myrepo/myapp:buildcache \
  -t myrepo/myapp:1.0.0 --push .
기능레거시 빌더BuildKit/buildx
빌드 실행 방식레이어를 순차적으로 하나씩 빌드의존성 그래프를 분석해 무관한 단계를 병렬 실행
캐시 단위레이어 전체 단위로만 캐시RUN --mount=type=cache로 특정 디렉토리만 세밀하게 캐시
시크릿 전달ARG/ENV로 전달 시 이미지 레이어에 흔적이 남을 위험--secret으로 전달 시 최종 이미지에 전혀 남지 않음
멀티 플랫폼아키텍처별로 각각 빌드 후 수동으로 매니페스트 관리buildx build --platform으로 한 번에 빌드 + push

Tip

RUN --mount=type=secret,id=npmrc npm ci처럼 시크릿을 마운트로 전달하면, 빌드가 끝난 뒤 그 값이 이미지 레이어 어디에도 남지 않습니다 — ARG로 비밀번호를 넘기면 docker history로 나중에 그대로 복원될 수 있다는 점과 대조적입니다.

Docker 네트워크

여기서는 Docker 네트워크을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

컨테이너를 아무 옵션 없이 실행하면 기본적으로 bridge 네트워크에 연결됩니다. 같은 bridge 네트워크에 속한 컨테이너끼리는 서비스 이름을 DNS처럼 사용해 서로를 찾을 수 있고, 호스트에서 컨테이너로 들어오려면 -p로 포트를 명시적으로 매핑해야 합니다.
다이어그램 렌더링 중…
네트워크 드라이버용도
bridge (기본값)같은 호스트 안 컨테이너 간 통신 — 대부분의 로컬/단일 서버 환경
host컨테이너가 호스트의 네트워크를 그대로 사용 (포트 매핑 불필요, 격리 약화)
none네트워크 완전 비활성화 — 배치 작업 등 통신이 필요 없는 경우
overlay여러 호스트에 걸친 컨테이너 통신 — Docker Swarm/멀티 호스트 환경

Tip

컨테이너 안에서 다른 컨테이너에 접속할 때는 localhost가 아니라 서비스 이름(예: db, redis)을 호스트명으로 써야 합니다 — 각 컨테이너는 자신만의 네트워크 네임스페이스를 가지므로 localhost는 컨테이너 자기 자신을 가리킵니다.

볼륨과 데이터 영속성

여기서는 볼륨과 데이터 영속성을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

컨테이너를 삭제하면 그 안에 쓰여진 파일도 함께 사라집니다. DB나 업로드 파일처럼 컨테이너 생명주기와 무관하게 데이터를 남겨야 한다면 반드시 볼륨이나 바인드 마운트로 호스트에 데이터를 분리해야 합니다.
다이어그램 렌더링 중…
방식설명주로 쓰는 곳
Named VolumeDocker가 관리하는 저장 공간 (-v pgdata:/data)DB, 애플리케이션 상태 등 컨테이너가 소유하는 데이터
Bind Mount호스트의 특정 경로를 그대로 연결 (-v ./src:/app/src)로컬 개발 중 소스 코드 실시간 반영
tmpfs메모리에만 저장, 컨테이너 종료 시 소멸민감한 임시 데이터, 캐시

Tip

로컬 개발 환경에서는 bind mount로 소스 코드를 연결해 코드를 고칠 때마다 이미지를 다시 빌드하지 않게 하고, 프로덕션 데이터는 named volume으로 관리하는 것이 일반적인 조합입니다.

Docker Compose로 다중 컨테이너 구성

여기서는 Docker Compose로 다중 컨테이너 구성을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

Docker Compose는 여러 컨테이너로 이루어진 애플리케이션을 하나의 YAML 파일로 정의하고 한 번에 띄우는 도구입니다. depends_on과 healthcheck를 함께 쓰면 DB가 실제로 요청을 받을 준비가 된 뒤에 API 컨테이너가 시작되도록 순서를 제어할 수 있습니다.
docker-compose.ymlYAML
services:
  api:
    build: .
    ports: ["3000:3000"]
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "user"]
      interval: 5s
      retries: 5

volumes:
  pgdata:

Tip

  • depends_on만 쓰면 "컨테이너가 시작됐는지"만 확인하고 "서비스가 요청을 받을 준비가 됐는지"는 보장하지 않습니다 — DB처럼 부팅 시간이 걸리는 서비스는 반드시 healthcheck의 condition: service_healthy와 함께 써야 합니다.
  • 2020년대 초반까지 파일 맨 위에 있던 version: "3.8" 같은 필드는 최신 Docker Compose(v2)에서는 더 이상 필요 없습니다 — 있어도 무시되지만, 새로 작성한다면 생략하는 것이 표준입니다.

Docker Swarm — 아키텍처

여기서는 Docker Swarm — 아키텍처을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

Docker Swarm은 Docker Engine에 기본 내장된 오케스트레이션 모드로, 별도 설치 없이 docker swarm init 한 줄이면 여러 대의 서버를 하나의 클러스터로 묶을 수 있습니다. 클러스터는 클러스터 상태(어떤 서비스가 몇 개 떠 있어야 하는지 등)를 Raft 합의 알고리즘으로 관리하는 Manager 노드와, 실제로 컨테이너를 실행하는 Worker 노드로 나뉩니다.
다이어그램 렌더링 중…
BASH
# 첫 번째 매니저 노드에서 클러스터 초기화
docker swarm init --advertise-addr 192.168.1.10

# 출력된 토큰으로 워커 노드를 클러스터에 합류
docker swarm join --token SWMTKN-1-xxxxx 192.168.1.10:2377

# 매니저를 추가로 합류시킬 때 쓰는 토큰은 별도 발급
docker swarm join-token manager

# 클러스터 노드 목록 & 역할 확인
docker node ls
항목ManagerWorker
역할클러스터 상태 저장, 스케줄링 결정, API 응답할당받은 태스크(컨테이너)만 실행
장애 허용N개 매니저 중 과반수(quorum)가 살아있어야 클러스터 동작워커 하나가 죽어도 매니저가 다른 노드에 태스크 재배치
권장 대수3, 5, 7대처럼 홀수 — (N-1)/2대까지 장애 허용워크로드 양에 맞춰 자유롭게 증설

Tip

매니저를 2대로 구성하면 오히려 위험합니다 — 1대가 죽으면 남은 1대는 전체의 과반(quorum)이 아니라서 클러스터가 정지합니다. 매니저는 반드시 홀수(3, 5, 7)로 구성하세요.

Swarm 서비스 배포 & 롤링 업데이트

여기서는 Swarm 서비스 배포 & 롤링 업데이트을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

Swarm에서는 docker run 대신 docker service create로 "몇 개의 복제본(replica)을 유지할지"를 선언합니다. 태스크(복제본) 하나가 죽으면 Swarm이 자동으로 다른 노드에 새 태스크를 배치해 replica 수를 원래대로 되돌리고, 이미지를 업데이트할 때도 전체를 한 번에 내리지 않고 몇 개씩 순차적으로 교체합니다.
다이어그램 렌더링 중…
BASH
# 서비스 생성 — 3개 복제본, 80번 포트로 클러스터 전체에 노출(ingress mesh)
docker service create --name web --replicas 3 -p 80:80 nginx:1.27

# 부하에 맞춰 즉시 스케일 조정
docker service scale web=6

# 이미지 롤링 업데이트 — 한 번에 1개씩, 10초 간격으로 순차 교체
docker service update \
  --image nginx:1.28 \
  --update-parallelism 1 \
  --update-delay 10s \
  --update-failure-action rollback \
  web

# 방금 배포에 문제가 있으면 이전 버전으로 즉시 롤백
docker service rollback web

# 서비스 상태 & 태스크별 배치 노드 확인
docker service ps web
플래그의미
--replicas유지할 태스크(컨테이너) 개수 — Swarm이 항상 이 수를 맞춰 자동 복구
--update-parallelism한 번에 몇 개의 태스크를 동시에 교체할지
--update-delay각 배치 교체 사이에 대기할 시간 — 헬스체크가 안정화될 시간을 확보
--update-failure-action업데이트 실패 시 동작 (pause 또는 rollback)

Tip

-p 80:80으로 서비스를 노출하면 Swarm의 ingress mesh 덕분에 클러스터의 어느 노드로 요청이 들어오든 실제로 그 태스크가 없는 노드라도 자동으로 올바른 컨테이너까지 라우팅됩니다 — 로드밸런서가 각 노드의 IP를 알 필요가 없습니다.

Docker Stack & Swarm vs Kubernetes

여기서는 Docker Stack & Swarm vs Kubernetes을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

Docker Stack은 이미 작성해둔 Compose 파일을 그대로 Swarm 클러스터에 배포하는 기능입니다. 여러 노드에 걸쳐 서비스를 배치해도 서로 통신할 수 있도록 overlay 네트워크를 자동으로 구성하고, 비밀번호 같은 민감한 값은 이미지에 넣지 않고 secret으로 별도 관리할 수 있습니다.
다이어그램 렌더링 중…
docker-compose.yml (Stack 배포용)YAML
services:
  api:
    image: myrepo/api:1.0.0
    ports: ["80:3000"]
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
    secrets:
      - db_password

  db:
    image: postgres:16-alpine
    deploy:
      placement:
        constraints: ["node.role == manager"]   # 데이터는 특정 노드에 고정
    secrets:
      - db_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    external: true
BASH
# 시크릿을 클러스터에 먼저 등록 (Git에는 값을 커밋하지 않음)
echo "s3cr3t" | docker secret create db_password -

# Compose 파일 그대로 Stack으로 배포
docker stack deploy -c docker-compose.yml myapp

docker stack services myapp   # 서비스별 replica 상태
docker stack ps myapp         # 태스크가 어느 노드에 배치됐는지
비교 항목Docker SwarmKubernetes
설치·학습 곡선Docker Engine에 내장 — 명령어 몇 개로 즉시 시작별도 설치 필요, 개념(Pod·Service·Ingress 등)이 훨씬 많음
적합한 규모노드 수십 대, 단순한 서비스 구성노드 수백~수천 대, 복잡한 멀티팀 운영
생태계Compose 파일 재사용 가능, 생태계는 상대적으로 작음Helm·Operator·서비스 메시 등 압도적으로 큰 생태계
선택 기준빠르게 띄우고 운영 부담을 최소화하고 싶을 때확장성·세밀한 제어·업계 표준 도구 연동이 필요할 때

Tip

"작게 시작해서 나중에 Kubernetes로 옮기면 되지 않을까"라는 생각으로 Swarm을 고르는 경우가 많은데, 두 시스템은 개념과 매니페스트가 상당히 달라 자동 마이그레이션은 불가능합니다 — 향후 대규모 확장이 확실하다면 처음부터 kubernetes 가이드로 시작하는 편이 나을 수 있습니다.

컨테이너 보안 & 취약점 스캔

여기서는 컨테이너 보안 & 취약점 스캔을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

컨테이너는 기본적으로 root 사용자로 실행되고, 호스트와 커널을 공유합니다. 이 두 가지 특성 때문에 이미지 안에서 실행 계정을 낮추고, 불필요한 권한과 공격 표면을 줄이는 것이 VM 환경보다 더 중요합니다. 여기에 더해 베이스 이미지에 알려진 취약점(CVE)이 없는지 배포 전에 스캔하는 것도 필수적인 절차입니다.
BASH
# Docker Scout — 이미지 취약점 요약 확인 (Docker Desktop에 내장)
docker scout quickview myrepo/myapp:1.0.0

# CVE 상세 목록 (심각도별)
docker scout cves myrepo/myapp:1.0.0

# 베이스 이미지를 더 안전한 버전으로 바꿀 수 있는지 추천
docker scout recommendations myrepo/myapp:1.0.0

# CI 파이프라인에서: Critical/High 취약점이 있으면 빌드 실패 처리
docker scout cves --exit-code --only-severity critical,high myrepo/myapp:1.0.0
항목하지 말아야 할 것대신 이렇게
실행 계정root로 그대로 실행Dockerfile에 USER 지정 (예: USER node)
베이스 이미지불필요하게 큰 풀 OS 이미지alpine, distroless 등 최소 이미지
시크릿 관리ENV나 Dockerfile ARG에 비밀번호 하드코딩Secrets Manager/환경변수 주입, --secret 빌드 옵션
이미지 취약점검증 없이 배포docker scout, trivy 등으로 CI에서 스캔

Tip

docker run --read-only로 컨테이너의 루트 파일시스템을 읽기 전용으로 만들면, 공격자가 컨테이너에 침투해도 실행 파일을 바꿔치기하기 어려워집니다 — 로그·캐시처럼 쓰기가 필요한 경로만 tmpfs나 볼륨으로 예외를 두세요.

베스트 프랙티스

이 섹션은 베스트 프랙티스을 실무 관점에서 정리합니다. 개념을 외우기보다, 어떤 상황에서 이 기준을 꺼내 쓸지에 초점을 맞춰보세요.

지금까지 다룬 내용을 실무에 적용할 때 반드시 챙겨야 할 체크리스트로 정리하면 다음과 같습니다.

Tip

  • .dockerignore로 node_modules, .git처럼 이미지에 불필요한 파일을 빌드 컨텍스트에서부터 제외하세요 — 빌드 속도와 이미지 크기 모두에 영향을 줍니다.
  • 비루트 사용자로 실행: Dockerfile에 USER node를 명시하세요.
  • 멀티 스테이지 빌드로 최종 이미지에서 빌드 도구를 제거하세요.
  • Alpine이나 distroless 기반 이미지로 공격 표면을 줄이세요.
  • 레이어 캐싱을 살리려면 COPY package.json을 먼저, 소스 코드 COPY는 나중에 배치하세요.
  • 이미지 태그로 latest 대신 커밋 SHA나 버전 태그를 써서 배포 추적과 롤백을 명확하게 하세요.

다음 단계

이 섹션은 다음 단계을 실무 관점에서 정리합니다. 개념을 외우기보다, 어떤 상황에서 이 기준을 꺼내 쓸지에 초점을 맞춰보세요.

🚀
Docker 다음은 Kubernetes

컨테이너 하나를 잘 만드는 법을 익혔다면, 다음은 여러 컨테이너를 여러 서버에 걸쳐 안정적으로 운영하는 문제입니다 — 장애 시 자동 재시작, 트래픽에 따른 오토스케일링, 무중단 배포는 Docker 단독으로는 다루기 어렵습니다.

연계 가이드: Kubernetes 가이드 · CI/CD 가이드 · AWS 가이드 (ECS Fargate로 컨테이너 배포)

Docker 실무 설계

Docker 실무 설계은 선택지가 갈리는 지점입니다. 표를 기준으로 각 방법의 쓰임새와 운영상의 차이를 비교해두면 이후 판단이 훨씬 쉬워집니다.

Docker는 이미지를 작게 만드는 것보다 재현 가능하고 안전한 런타임을 만드는 것이 중요합니다. build stage, runtime user, secret, volume을 분리해야 합니다.
결정 지점확인 질문실무 기준
경계Docker 코드에서 바뀌기 쉬운 부분은 어디인가?입출력, 설정, 외부 연동, 핵심 규칙을 분리합니다.
상태상태가 어디서 생성되고 어디서 사라지는가?상태 소유자와 수명 주기를 코드로 드러냅니다.
장애실패했을 때 호출자는 무엇을 받는가?timeout, fallback, error contract를 먼저 정합니다.

Docker 운영 기준

이 섹션은 Docker 운영 기준을 실무 관점에서 정리합니다. 개념을 외우기보다, 어떤 상황에서 이 기준을 꺼내 쓸지에 초점을 맞춰보세요.

이미지 cache, layer size, healthcheck, restart policy, log driver, resource limit을 관리해야 합니다.

Tip

  • multi-stage build
  • non-root user
  • healthcheck
  • image scan

Docker 검증 전략

Docker 검증 전략은 선택지가 갈리는 지점입니다. 표를 기준으로 각 방법의 쓰임새와 운영상의 차이를 비교해두면 이후 판단이 훨씬 쉬워집니다.

Dockerfile lint, vulnerability scan, reproducible build, container smoke test를 포함합니다.
품질 축검증 방법완료 기준
정확성정상/실패 케이스를 자동화합니다.핵심 시나리오가 재현 가능하게 통과합니다.
회귀 방지버그 수정 시 동일 케이스를 테스트로 남깁니다.같은 장애가 다시 배포되지 않습니다.
운영성로그, 메트릭, 알림을 확인합니다.문제가 생겼을 때 원인 추적 경로가 있습니다.
← 이전 가이드Linux다음 가이드 →CI/CD