Docker는 전통적인 하이퍼바이저 기반 가상머신(VM)과 달리, 리눅스 커널이 제공하는 다양한 기능을 조합해 호스트 커널을 공유하면서도 독립된 프로세스 환경을 제공하는 경량 컨테이너 플랫폼이다. OS 수준의 가상화(OS-level virtualization)라고 부르며, 프로세스 격리와 자원 제어만으로 빠르고 효율적인 애플리케이션 배포·운영을 가능케 한다.
컨테이너 vs VM
가상머신 (VM) | 컨테이너(Docker) | |
커널 | 각 VM마다 별도 커널과 OS | 호스트 커널을 공유 |
가동 시간 | 수십 초 이상 (부팅 필요) | 수 밀리초~수 초 (프로세스로 실행) |
오버헤드 | 메모리·디스크·CPU 오버헤드 큼 | 최소한의 사용자 공간 레이어만 추가 |
격리 수준 | 꽉 막힌 격리 | 네임스페이스·Cgroups 기반 격리 |
컨테이너는 결국 “독립된 프로세스”이므로, VM과 달리 오버헤드 없이 즉시 실행할 수 있다.
Docker를 가능하게 한 핵심 리눅스 기술
1. 네임스페이스 (Namespace)
리눅스 커널이 프로세스별로 보이는 리소스 영역(Resource View)을 분리한다. Docker는 여러 네임스페이스를 결합해 컨테이너 격리를 구현한다.
네임스페이스 종류 | 설명 |
PID | 프로세스 ID 분리 (컨테이너 안은 1번 PID부터 시작) |
Mount | 파일 시스템 분리 (루트 디렉토리 / 분리) |
Network | 네트워크 인터페이스(IP 주소, 포트 등) 격리 |
IPC | 프로세스 간 통신 리소스 분리 |
UTS | 호스트명(Hostname)과 도메인명 분리 |
User | UID/GID 맵핑으로 비권한 사용자 환경 제공 |
👉 이 덕분에, 컨테이너 안에서는 자신만의 프로세스, 네트워크, 파일 시스템을 가진 것처럼 보인다.
2. 컨트롤 그룹 (Cgroup)
프로세스 그룹별로 CPU, 메모리, 블록 I/O, 네트워크 대역폭 등을 제한·계량·격리한다.
- CPU 제한: --cpus=".5" (전체 CPU의 50% 사용)
- 메모리 제한: -m 256m (256MB 상한)
- 블록 I/O 제한: --device-write-bps, --device-read-bps
- Cgroup v2: 단일 계층 구조로 간단해진 리소스 관리
docker run --rm --cpus=".5" -m 256m nginx
👉 그래서 하나의 컨테이너가 서버 자원을 독점하는 상황을 방지하고, 여러 컨테이너가 자원을 공정하게 나눠 쓸 수 있게 한다.
3. 유니온 파일 시스템(OverlayFS)
Copy-on-Write 기반의 다중 레이어 파일 시스템으로, 베이스 이미지 레이어는 읽기 전용으로 유지하고 컨테이너의 변경사항만 별도 레이어에 기록한다.
- Lower (읽기 전용): 베이스 이미지 레이어
- Upper (쓰기 가능): 실행 중 생성된 변경사항
- Work (작업 디렉토리): 오버레이 동작에 필요한 임시 디렉토리
mount -t overlay overlay \
-o lowerdir=/image/base,upperdir=/container/diff,workdir=/container/work \
/container/rootfs
👉 파일시스템 복사 없이도 이미지 공유와 빠른 컨테이너 생성이 가능하다.
4 루트 파일시스템 분리: chroot, pivot_root
- chroot: 프로세스의 루트 디렉토리를 변경하지만, 네임스페이스 없이 우회 가능
- pivot_root: 마운트 네임스페이스 내에서 전체 파일시스템을 교체해 더 견고한 격리 제공
Docker는 내부적으로 pivot_root를 사용해 컨테이너마다 완전 분리된 루트 파일시스템을 구성한다.
컨테이너 런타임의 진화: libcontainer → containerd → runc
- libcontainer (Docker v1.0): 리눅스 네임스페이스·Cgroups를 직접 다루는 Go 라이브러리
- containerd (추출된 런타임): libcontainer 기반으로 컨테이너 라이프사이클(생성·실행·종료) 관리
- runc (OCI 표준 런타임): containerd가 호출하는 최소 실행 바이너리 (libcontainer → OCI 호환)