컨테이너란 무엇인가? — Docker 완전 정복 1편
컨테이너의 정의, 내부 구조, 격리 메커니즘(namespace/cgroup)을 이해하고 왜 컨테이너가 현대 소프트웨어 배포의 표준이 됐는지 알아봅니다.
소프트웨어를 한 번 빌드하면 어디서든 동일하게 실행할 수 있다면 얼마나 편할까요? 컨테이너는 그 오래된 소원을 현실로 만든 기술입니다. “내 컴퓨터에서는 잘 됐는데” 라는 말이 더 이상 통하지 않는 이유가 바로 컨테이너 덕분입니다. 이 글에서는 컨테이너가 무엇인지, 어떤 Linux 커널 기능 위에서 동작하는지, 그리고 왜 그토록 빠르고 가벼운지 처음부터 차근차근 살펴봅니다.
컨테이너의 정의
컨테이너는 격리된 프로세스입니다. 가상 머신처럼 별도의 OS를 올리는 것이 아니라, 호스트의 Linux 커널을 그대로 공유하면서 프로세스가 마치 자기만의 OS 위에서 돌아가는 것처럼 느끼게 해 주는 환경입니다.
좀 더 정확히 말하면, 컨테이너는 다음 세 가지 구성 요소를 하나로 묶은 실행 단위입니다:
- 애플리케이션 바이너리 — 실제로 실행할 프로그램
- 의존성(Libraries/Dependencies) — 프로그램이 필요로 하는 모든 라이브러리와 설정 파일
- 격리된 파일시스템 — OverlayFS 레이어로 구성된 읽기 전용 이미지와 쓰기 가능한 레이어
컨테이너가 시작될 때 커널은 새 프로세스에 여러 namespace를 부여해 독립적인 시야를 제공하고, cgroup으로 자원 사용량을 제한합니다.
컨테이너 ≠ 프로세스, 컨테이너 ≠ VM
컨테이너를 처음 접할 때 흔히 두 가지 혼란이 생깁니다.
“그냥 프로세스와 뭐가 달라요?”
일반 프로세스는 시스템 전체의 프로세스 트리, 네트워크 인터페이스, 파일시스템을 그대로 볼 수 있습니다. 컨테이너 내 프로세스는 자신이 속한 namespace 안에서만 세상을 봅니다. 호스트의 PID 1은 보이지 않고, 컨테이너 안에서 자신이 PID 1입니다. 네트워크도 마찬가지로 독립된 가상 인터페이스를 가집니다.
“VM과 뭐가 달라요?”
VM은 하이퍼바이저 위에 별도의 커널과 OS를 통째로 올립니다. 수백 MB ~ 수 GB의 이미지, 분 단위의 부팅 시간, 게스트 OS의 메모리 점유가 필요합니다. 컨테이너는 커널을 공유하기 때문에 이미지는 수십 MB 수준이고, 시작은 수백 밀리초면 충분합니다.
Linux 커널이 제공하는 두 기둥
컨테이너의 동작 원리는 Linux 커널의 두 기능에 의존합니다.
Namespace — 격리의 핵심
Namespace는 프로세스가 “볼 수 있는 것”을 제한합니다. 동일한 커널 위에서 서로 다른 컨테이너가 각자 독립적인 세계를 가집니다.
| Namespace | 격리 대상 |
|---|---|
pid | 프로세스 ID 트리 |
net | 네트워크 인터페이스, 라우팅 테이블 |
mnt | 파일시스템 마운트 포인트 |
uts | hostname, domainname |
ipc | System V IPC, POSIX 메시지 큐 |
user | UID/GID 매핑 |
cgroups — 자원 제한의 핵심
Control Groups(cgroups)는 프로세스 그룹에 자원 상한을 부여합니다. --memory=512m 옵션을 주면 해당 컨테이너의 cgroup에 메모리 상한이 설정됩니다. 제한을 초과하면 OOM killer가 작동해 프로세스를 종료합니다.
이미지와 컨테이너의 관계
이미지는 실행 파일과 의존성을 담은 읽기 전용 스냅샷입니다. 클래스(class)에 비유할 수 있습니다. 컨테이너는 그 이미지를 실행한 인스턴스입니다. 동일한 이미지로 여러 컨테이너를 동시에 띄울 수 있고, 각 컨테이너는 자신만의 쓰기 가능한 레이어를 가집니다.
Ubuntu 22.04 이미지 (base)
└── Node.js 20 레이어
└── 앱 코드 레이어 ← docker build로 추가
└── [writable] ← 컨테이너 실행 시 생성
컨테이너를 삭제하면 writable 레이어는 사라지지만 이미지는 남아 있습니다. 데이터를 영속적으로 보관하려면 **볼륨(Volume)**을 사용해야 합니다 — 이 내용은 시리즈 후반에서 다룹니다.
컨테이너가 표준이 된 이유
컨테이너가 현대 인프라의 표준이 된 데는 기술적 이유 외에도 실용적 이유가 있습니다.
- 환경 일관성: 개발 노트북, CI 서버, 프로덕션 클라우드 어디서나 동일한 실행 환경
- 빠른 배포: 수 초 안에 시작·종료, 수십 개를 동시에 실행 가능
- 자원 효율: VM 대비 훨씬 낮은 오버헤드, 밀도 높은 배포 가능
- 이식성: OCI(Open Container Initiative) 표준 덕분에 어느 런타임에서나 실행 가능
정리
컨테이너는 Linux 커널의 namespace와 cgroup 위에 구축된 격리된 프로세스 실행 환경입니다. VM처럼 별도 OS를 올리지 않기 때문에 가볍고 빠르며, 이미지라는 불변의 패키지 덕분에 환경 재현이 완벽합니다. 다음 글에서는 컨테이너와 VM을 더 구체적으로 비교해 언제 어느 것을 선택해야 하는지 알아봅니다.
다음 글: 컨테이너 vs 가상 머신 — 무엇을 선택할까?
읽어주셔서 감사합니다. 😊