Part 1. Docker 기본 과정

Docker 개요

학습 목표

  • 컨테이너화 기술이 등장한 배경과 필요성을 설명할 수 있다.

  • 실제 개발 현장의 사례를 통해 컨테이너를 사용하는 이유를 설명할 수 있다.

  • Docker와 전통적인 가상 머신(VM)의 차이점을 비교할 수 있다.

  • Docker의 핵심 구성요소(이미지, 컨테이너, 레지스트리)의 개념과 관계를 설명할 수 있다.

  • Docker 엔진의 내부 구조(CLI, REST API, dockerd, containerd)를 설명할 수 있다.

  • 이미지가 레이어로 쌓이는 구조와 컨테이너 쓰기 레이어의 역할을 설명할 수 있다.

1. 컨테이너화 기술의 등장

컨테이너화는 애플리케이션을 배포하고 실행하는 현대적인 방식으로, 개발에서 운영에 이르기까지 일관된 환경을 제공한다. 이 기술은 애플리케이션과 그 종속성을 컨테이너라는 격리된 환경에 패키징하여, 어느 환경에서나 동일하게 실행될 수 있도록 한다.

이러한 접근 방식은 개발(Dev) · 테스트(QA) · 운영(Prod) 환경 간의 차이로 발생하는 "내 PC에서는 되는데?" 문제를 근본적으로 해결해준다.

컨테이너화의 주요 이점

  1. 환경 일관성 — 개발·테스트·운영 환경의 차이를 최소화한다.

  2. 빠른 배포 및 확장 — 애플리케이션과 서비스를 신속하게 배포하고 스케일링할 수 있다.

  3. 리소스 효율성 — 가상 머신(VM) 대비 오버헤드가 적어 동일 서버에서 더 많은 앱을 실행할 수 있다.

  4. 이식성(Portability) — 로컬·클라우드·온프레미스 어디서든 동일하게 실행된다.

  5. 격리성 — 각 컨테이너는 독립된 공간에서 실행되므로 서로 영향을 주지 않는다.

2. 왜 컨테이너를 사용하는가?

컨테이너가 필요한 이유를 실제 개발 현장의 사례를 통해 알아보자.

2-1. "내 PC에서는 되는데요" 문제

같은 코드인데 실행되는 곳마다 결과가 달라지는 일이 흔하다. 원인은 코드가 아니라 코드 바깥에 있다. JDK 버전, DB 버전, 포트처럼 코드가 기대하는 것들이 서버마다 다르기 때문이다.

컨테이너 없이 배포했을 때와 컨테이너로 배포했을 때의 차이

런타임과 설정을 이미지 안에 고정하면 실행 위치가 바뀌어도 환경은 그대로다

컨테이너는 이 문제를 환경을 코드와 함께 포장하는 방식으로 해결한다. 실행할 JDK, 필요한 라이브러리, 설정 파일까지 이미지 하나에 담아 두면, 그 이미지를 받는 쪽은 자기 서버에 무엇이 깔려 있든 같은 환경을 얻는다.

2-2. 신규 개발자 온보딩

컨테이너 없이 신규 입사자가 개발 환경을 직접 세팅하면 수 시간이 걸린다.

# 컨테이너 사용 시 — 단 3줄로 전체 개발 환경 실행
git clone https://github.com/company/project.git
cd project
docker compose up

Java, Node.js, DB, Redis 등 모든 의존성이 이미 이미지에 포함되어 있어, 신규 개발자는 설치 없이 바로 개발을 시작할 수 있다.

2-3. 여러 프로젝트의 의존성 충돌 해결

개발자가 동시에 여러 프로젝트를 진행하면 의존성이 충돌하는 경우가 많다.

프로젝트

요구 버전

컨테이너 없이

컨테이너 사용 시

프로젝트 A

Java 11, MySQL 5.7

전역 설치 — 버전 충돌

컨테이너 A에서 독립 실행

프로젝트 B

Java 21, MySQL 8.4

매번 버전 전환 필요

컨테이너 B에서 독립 실행

프로젝트 C

Python 3.8, PostgreSQL

가상 환경 별도 관리

컨테이너 C에서 독립 실행

2-4. 배포 자동화 (CI/CD 파이프라인)

컨테이너 이전에는 배포 시마다 서버에 직접 접속해 패키지를 설치하고 설정 파일을 수정해야 했다.

[개발자 코드 Push]
       ↓
[GitHub Actions / Jenkins]
       ↓
docker build -t myapp:v1.2.3 .   ← 이미지 빌드
       ↓
docker push myregistry/myapp     ← 레지스트리에 업로드
       ↓
[운영 서버]
docker pull myregistry/myapp     ← 최신 이미지 내려받기
docker compose up -d             ← 새 이미지로 교체 (잠깐 끊긴다)

서버 환경을 건드리지 않고 이미지만 교체하면 배포가 완료되므로, 롤백도 이전 버전 이미지로 교체하면 된다. 다만 docker compose up -d 는 기존 컨테이너를 내리고 새로 띄우므로 그 사이 요청이 끊긴다. 끊김 없이 교체하는 방법(무중단 배포)은 Part 3·4 에서 다룬다.

CI/CD 파이프라인

CI/CD 파이프라인

CI (Continuous Integration, 지속적 통합) — 개발자가 코드를 push할 때마다 자동으로 빌드하고 테스트를 돌려서 "이 코드가 문제없는가?"를 검증한다. 여러 개발자가 동시에 작업해도 코드가 충돌하거나 망가지는 것을 빠르게 발견할 수 있다.

CD (Continuous Delivery/Deployment, 지속적 배포) — CI를 통과한 코드를 자동으로 서버에 배포하는 단계이다. Delivery는 "스테이징까지 자동, 운영은 수동 승인", Deployment는 "운영까지 완전 자동"이라는 차이가 있다.

2-5. 마이크로서비스 아키텍처

대형 서비스는 하나의 거대한 앱(모놀리식) 대신, 기능별로 분리된 마이크로서비스 구조로 운영한다.

모놀리식 구조와 마이크로서비스 구조 비교

한 덩어리로 묶으면 함께 늘리고 함께 멈추지만, 나눠 담으면 필요한 것만 늘리고 터진 것만 멈춘다

  • 각 서비스를 독립적으로 배포·확장·재시작 할 수 있다.

  • 특정 서비스에 장애가 발생해도 다른 서비스는 계속 응답한다 — 장애 격리.

  • 트래픽이 몰리는 서비스만 컨테이너 수를 늘린다 — 선택적 스케일링. 위 그림에서는 주문 서비스만 3개로 늘렸다.

  • 대신 서비스 사이의 통신·배포·추적할 대상이 늘어나므로, 규모가 작을 때는 모놀리식이 더 나을 수도 있다.

3. Docker의 등장과 현재

3-1. 탄생 배경

2013년 이전에도 리눅스에는 LXC(Linux Containers)라는 컨테이너 기술이 존재했다. 하지만 LXC는 설정이 복잡하고 이식성이 낮아 일반 개발자가 사용하기 어려웠다.

Solomon Hykes는 2013년 PyCon에서 Docker를 처음 공개했다. Docker는 LXC 위에 사용하기 쉬운 인터페이스와 이미지 레이어 시스템을 얹어, 누구나 컨테이너를 쉽게 만들고 공유할 수 있도록 만들었다.

Docker 주요 연혁

  • 2013년 3월 — PyCon에서 오픈소스로 첫 공개. 발표 당일 GitHub 스타 수가 폭발적으로 증가

  • 2014년 3월 — Docker 0.9에서 자체 런타임 libcontainer를 기본 실행 드라이버로 채택. LXC 의존성에서 벗어났다

  • 2014년 6월 — Docker 1.0 정식 출시. Google, Microsoft, Amazon 등 주요 클라우드 벤더 지원 선언

  • 2015년 — Docker Compose, Docker Swarm, Docker Hub 생태계 본격 확장

  • 2017년 — 컨테이너 런타임 표준화를 위해 containerd를 CNCF(Cloud Native Computing Foundation)에 기증

  • 2020년 12월 — Kubernetes 1.20이 dockershim(Docker 런타임 지원) deprecation 발표. 실제 제거는 2022년 5월 릴리스된 Kubernetes 1.24 부터이고, 이후로는 containerd·CRI-O를 직접 사용한다

  • 2021년 8월 → 2022년 1월 — Docker Desktop 유료화. 2021년 8월에 정책이 발표되고 2022년 1월 31일 유예가 끝났다. 대기업 기준이며 적용 기준과 요금제는 이후로도 여러 번 바뀌었으니 Docker 공식 요금 페이지에서 확인한다. 이 시기에 Rancher Desktop·Podman 등 대안 도구가 주목받았다

  • 2026년 현재 — 컨테이너 이미지 빌드 도구로서의 입지는 여전히 압도적, 기업 표준으로 자리매김

3-2. Docker가 가져온 변화

Docker 등장 이전과 이후 개발 문화는 크게 달라졌다.

영역

Docker 이전

Docker 이후

배포 방식

서버에 직접 SSH 접속 후 수동 설치

이미지 교체로 배포 완료

환경 관리

서버마다 수동 설정, 문서화 의존

Dockerfile 한 파일로 환경 코드화

협업

"내 PC에서는 되는데" 문제 빈번

이미지 공유로 환경 차이 제거

인프라 철학

서버를 오래 유지·관리 (Pet)

필요 시 생성, 불필요 시 삭제 (Cattle)

3-3. 현재의 컨테이너 생태계

Docker는 컨테이너 대중화의 기폭제가 되었고, 현재는 더 넓은 생태계가 형성되어 있다.

[컨테이너 생태계 지형도, 2026]

이미지 빌드          런타임                  오케스트레이션
──────────          ──────                  ──────────────
Docker Build   →   containerd          →   Kubernetes (K8s)
BuildKit            CRI-O                   Docker Swarm
Podman              runc                    Amazon ECS
Kaniko                                      Google GKE
                                            Azure AKS
  • Kubernetes(K8s): Google이 공개한 컨테이너 오케스트레이션 플랫폼. 수백~수천 개의 컨테이너를 자동으로 배포·확장·복구한다. 컨테이너를 대규모로 운영하는 조직에서 사실상 표준으로 쓰이고, 주요 클라우드는 모두 관리형 K8s(EKS·GKE·AKS)를 제공한다.

  • Podman: Docker 명령어와 호환되면서 데몬 없이 동작하는 대안 런타임. 보안이 중요한 환경에서 선호된다.

  • containerd / CRI-O: Kubernetes가 직접 사용하는 컨테이너 런타임. Docker 없이 컨테이너를 실행한다.

Docker를 배워야 하는 이유 — 런타임 경쟁에서 Docker의 점유율이 분산되고 있지만, Dockerfile 형식과 컨테이너 이미지 빌드·관리 방식은 사실상 업계 표준이다. Docker를 이해하면 Kubernetes, AWS ECS, Google Cloud Run 등 어떤 환경에서도 컨테이너를 다룰 수 있다.

3-4. 국내외 활용 현황

컨테이너 기술은 이미 대부분의 IT 기업에서 기본 인프라로 사용되고 있다.

기업 / 서비스

활용 사례

Netflix

자체 컨테이너 관리 플랫폼 Titus 를 만들어 오픈소스로 공개했다

카카오

사내 Kubernetes 플랫폼 DKOS 로 서비스를 운영한다고 기술 행사에서 발표했다

네이버 클라우드

관리형 Kubernetes 상품(Ncloud Kubernetes Service)을 외부 고객에게 판매한다

AWS · GCP · Azure

컨테이너 전용 서비스(ECS·EKS, Cloud Run·GKE, AKS)를 핵심 상품으로 둔다

스타트업 전반

초기부터 ECS·Cloud Run 같은 관리형 컨테이너 서비스로 인프라를 꾸리는 경우가 많다

기업의 내부 구성은 수시로 바뀌고 외부에 전부 공개되지도 않는다. 면접에서 이런 사례를 말할 때는 그 회사의 기술 블로그·발표 자료를 직접 확인하고 인용하는 편이 좋다.

4. Docker vs. 전통적인 가상화(VM) 비교

Docker 컨테이너와 가상 머신 비교

Docker 컨테이너 vs 가상 머신

4-1. Docker 컨테이너 기반 가상화

구성 레이어

설명

하드웨어 인프라

물리 서버

호스트 OS

Linux / Windows / macOS (Windows·macOS는 내부 Linux VM을 거친다)

Docker 엔진

컨테이너 관리 플랫폼

컨테이너

앱 + 라이브러리 + 바이너리/설정만 포함

주요 특징

  • 컨테이너는 호스트 OS의 커널을 공유한다.

  • 게스트 OS가 필요 없어 가볍고 시작 시간이 빠르다.

  • 애플리케이션과 필요한 의존성만 포함하므로 이미지 크기가 작다.

"호스트 커널을 공유한다"가 그대로 성립하는 것은 Linux 호스트뿐이다. 컨테이너는 Linux 커널 기능(namespace, cgroup)으로 격리되므로 Linux 커널 위에서만 돌아간다.

Windows와 macOS에는 그 커널이 없다. 그래서 Docker Desktop은 내부에 Linux 가상 머신(Windows는 WSL2, macOS는 자체 VM)을 띄우고, 컨테이너는 호스트가 아니라 그 VM의 커널을 공유한다. 명령어를 치는 곳은 Windows지만 컨테이너가 실제로 실행되는 곳은 그 안의 Linux다.

Named Volume의 데이터는 Windows의 C: 어딘가가 아니라 WSL2 가상 파일시스템 안에 저장되므로 탐색기로 열리지 않는다(Docker 기본 명령어의 볼륨 실습 참고). VM을 한 겹 거치기 때문에 Linux 호스트보다 파일 I/O가 느린 것도 같은 이유다.

4-2. 전통적인 가상화 — VM (Virtual Machine)

구성 레이어

설명

하드웨어 인프라

물리 서버

호스트 OS

Linux / Windows

하이퍼바이저

VM을 생성·관리하는 소프트웨어 계층 (예: VMware, VirtualBox, Hyper-V)

가상 머신

게스트 OS + 앱 + 라이브러리 전체 포함

주요 특징

  • 각 VM은 완전한 게스트 OS를 포함하므로 용량이 크다.

  • 하이퍼바이저를 통해 하드웨어 자원을 가상화한다.

  • 호스트 OS와 완전히 격리되나, 부팅 시간이 길고 리소스 소모가 많다.

4-3. 한눈에 비교

항목

Docker 컨테이너

가상 머신(VM)

OS 포함 여부

커널 공유 (게스트 OS 없음)

게스트 OS 포함

시작 시간

수 초 이내

수십 초 ~ 수 분

이미지/디스크 크기

MB 단위

GB 단위

격리 수준

프로세스 수준 격리

하드웨어 수준 격리

이식성

매우 높음

상대적으로 낮음

5. Docker 핵심 구성요소

Docker를 이루는 세 가지 핵심 개념을 먼저 이해해야 한다.

5-1. 이미지 (Image)

  • 컨테이너를 실행하기 위한 읽기 전용 템플릿이다.

  • OS, 런타임, 애플리케이션 코드, 설정 파일 등이 레이어(Layer) 구조로 쌓여 있다.

  • Dockerfile을 작성하여 직접 빌드하거나, Docker Hub에서 공개 이미지를 내려받아 사용한다.

5-2. 컨테이너 (Container)

  • 이미지를 기반으로 실제로 실행되는 인스턴스이다.

  • 하나의 이미지로 여러 컨테이너를 동시에 실행할 수 있다.

  • 컨테이너를 삭제해도 이미지는 그대로 남는다.

5-3. 레지스트리 (Registry)

  • 이미지를 저장하고 공유하는 저장소이다.

  • 공개 레지스트리로는 Docker Hub(hub.docker.com)가 가장 널리 사용된다.

  • 기업 내부에서는 Private Registry를 구축하여 사용하기도 한다.

이미지 → 컨테이너 관계: 이미지는 클래스(Class), 컨테이너는 인스턴스(Instance) 에 비유할 수 있다.

6. Docker 엔진 구조

Docker 엔진은 클라이언트-서버 아키텍처로 동작한다. 사용자가 입력한 CLI 명령어가 REST API를 통해 Docker 데몬으로 전달되고, 데몬이 실제 컨테이너·이미지·네트워크·볼륨을 관리한다.

6-1. 구성요소 개요

구성요소

역할

Docker CLI

사용자가 명령어를 입력하는 인터페이스. docker build, docker run 등의 명령어를 처리한다.

REST API

CLI와 데몬 사이의 통신 규약. HTTP 또는 Unix 소켓을 통해 요청을 전달한다.

Docker 데몬 (dockerd)

REST API 요청을 수신하고 실제 작업을 수행하는 백그라운드 프로세스. 이미지·컨테이너·네트워크·볼륨을 생성하고 관리한다.

containerd

데몬 하위에서 실제 컨테이너 런타임을 제어하는 데몬. 이미지 전송·저장·실행을 담당한다.

6-2. 동작 흐름

사용자
  │
  ▼
Docker CLI  ──── REST API (HTTP / Unix Socket) ────▶  dockerd (Docker 데몬)
                                                            │
                                              ┌─────────────┼─────────────┐
                                              ▼             ▼             ▼
                                          컨테이너        이미지        네트워크/볼륨
                                          관리            관리          관리
                                              │
                                              ▼
                                         containerd
                                              │
                                              ▼
                                      runc (컨테이너 실행)

6-3. 아키텍처 구조도

Docker 엔진 아키텍처

Docker 엔진 아키텍처

6-4. 핵심 포인트

  • CLI와 데몬은 분리되어 있다. 같은 호스트뿐 아니라 원격 호스트의 데몬에도 연결할 수 있다.

  • REST API가 중간 통신 계층 역할을 하므로, CLI 외에도 다른 애플리케이션에서 Docker를 제어할 수 있다.

  • dockerd 는 직접 컨테이너를 실행하지 않고, containerd → runc 순서로 위임하여 실제 컨테이너를 구동한다.

7. 이미지 레이어 스택

이미지는 하나의 통짜 파일이 아니라 레이어(Layer)가 쌓인 것이다. Dockerfile 한 줄이 레이어 하나를 만들고, 그 레이어들이 아래에서 위로 겹쳐 하나의 파일 시스템처럼 보인다.

이미지 레이어 스택과 컨테이너 쓰기 레이어

이미지 레이어는 읽기 전용이고, 컨테이너마다 그 위에 쓰기 레이어가 한 장 얹힌다

레이어

성격

누가 갖는가

베이스 이미지 레이어

읽기 전용

이미지 — 같은 베이스를 쓰는 모두가 공유

애플리케이션 코드 레이어

읽기 전용

이미지 — 그 이미지를 쓰는 컨테이너가 공유

컨테이너 쓰기 레이어

읽기·쓰기

컨테이너마다 하나씩, 컨테이너를 지우면 사라짐

이 구조에서 세 가지가 따라 나온다.

  • 같은 이미지로 컨테이너를 여러 개 띄워도 디스크가 거의 늘지 않는다. 읽기 전용 레이어는 복사되지 않고 공유되며, 새로 생기는 것은 빈 쓰기 레이어뿐이다.

  • 컨테이너 안에서 고친 것은 컨테이너를 지우면 함께 사라진다. 변경은 이미지가 아니라 그 컨테이너의 쓰기 레이어에만 기록되기 때문이다. 데이터를 남기려면 볼륨이 필요하다.

  • 한 번 만들어진 레이어는 바뀌지 않는다. 그래서 Docker는 바뀌지 않은 레이어를 다시 만들지 않고 캐시에서 꺼내 쓴다. 이미지를 빠르게 다시 빌드할 수 있는 이유이자, Dockerfile의 명령 순서가 빌드 속도를 좌우하는 이유다.

레이어를 직접 만들고 캐시를 다루는 방법은 이미지 생성 및 관리에서 이어서 다룬다.

마지막 수정 2026년 10월 23일