많은 개발자들이 Docker를 “가상머신보다 가볍다”라고 설명하지만,
도대체 왜 가볍고 어떻게 동작하는지는 잘 모르는 경우가 많습니다.
사실 컨테이너의 핵심은 특별한 비밀 기술이 아니라, 리눅스 커널이 오래전부터 제공하던 기능을 잘 조합한 것입니다.
이번 글에서는 네임스페이스(namespace), cgroups(control groups)를 중심으로 컨테이너의 내부 구조를 살펴보고,
Docker 외의 실행 도구도 함께 정리하겠습니다.
1. 컨테이너는 작은 가상 컴퓨터일까?
컨테이너를 처음 접하면 “내 PC 안에 또 다른 작은 컴퓨터가 생기는구나”라고 생각하기 쉽습니다.
하지만 엄밀히 말하면, 컨테이너는 새로운 운영체제를 부팅하지 않습니다.
- 컨테이너는 리눅스 커널을 그대로 공유하면서
- 프로세스들을 격리해 마치 독립된 환경처럼 보이게 하는 것입니다.
겉으로 보기엔 가상머신처럼 보이지만, 내부적으로는 그냥 리눅스 프로세스일 뿐입니다.
2. 네임스페이스(namespace): 격리의 비밀
네임스페이스는 “같은 커널 위에서 실행되는 프로세스들을 서로 다른 세상처럼 보이게 하는 기술”입니다. 주요 네임스페이스 종류는 다음과 같습니다.
- PID 네임스페이스: 프로세스 번호(PID)를 분리. → 컨테이너 안에서는 1번 프로세스부터 시작하는 것처럼 보임.
- NET 네임스페이스: 네트워크 인터페이스와 포트 분리. → 컨테이너마다 독립적인 가상 네트워크 카드 할당.
- MNT 네임스페이스: 파일 시스템 마운트 분리. → 각 컨테이너가 서로 다른 디렉토리 구조를 갖는 것처럼 동작.
- UTS 네임스페이스: 호스트 이름과 도메인 분리. → 컨테이너마다 별도의 호스트명을 가질 수 있음.
docker exec -it 컨테이너ID ps -ef를 실행하면 호스트의 PID와 완전히 다른 번호 체계를 볼 수 있습니다.
이것이 바로 네임스페이스 덕분입니다.
3. cgroups(control groups): 자원 통제
네임스페이스가 “보이는 세계”를 분리한다면, cgroups는 자원의 사용량을 제한하는 기술입니다.
- CPU 사용률을 일정 비율로 제한
- 메모리 사용량을 상한선으로 고정
- 디스크 I/O 속도 제어
예를 들어, 메모리 제한을 건 컨테이너 실행:
docker run -m 512m --memory-swap=512m nginx
이 컨테이너는 512MB 이상의 메모리를 쓸 수 없습니다.
만약 초과하면 OOM(Out Of Memory) 에러와 함께 강제로 종료됩니다.
즉, cgroups 덕분에 한 컨테이너가 서버 전체 리소스를 독식하는 문제를 막을 수 있습니다.
4. 컨테이너 런타임: runc와 containerd
Docker라고 하면 모든 것을 한 프로그램이 하는 것처럼 보이지만, 사실 내부에는 여러 계층이 있습니다.
- runc: 리눅스 네임스페이스와 cgroups를 직접 호출해 컨테이너 프로세스를 띄우는 도구.
- containerd: 여러 컨테이너를 관리(시작, 중지, 삭제)하는 상위 레벨 런타임. runc를 내부적으로 사용.
- Docker Engine: containerd 위에서 이미지 빌드, 네트워크 관리, 레지스트리 연동까지 담당하는 종합 플랫폼.
Docker 없이도 runc나 containerd만으로 컨테이너를 실행할 수 있습니다.
5. Docker의 대안들: Podman과 기타 도구
컨테이너 기술이 표준화되면서 Docker 말고도 다양한 대안이 등장했습니다.
- Podman: Docker와 호환되는 명령어를 제공하지만, 데몬 없이 동작. 보안 측면에서 장점이 있음.
- CRI-O: Kubernetes를 위해 경량화된 컨테이너 런타임.
- LXC/LXD: Docker 이전부터 존재하던 리눅스 컨테이너 기술.
컨테이너 실행 자체는 Docker가 아니어도 가능하며, Docker는 개발자가 쓰기 쉽게 감싼 패키지일 뿐입니다.
컨테이너의 실체는 “리눅스 커널 기능을 활용한 프로세스 격리와 자원 제어”입니다.
- 네임스페이스로 서로 다른 세계처럼 보이게 하고
- cgroups로 자원 한도를 걸어두며
runc,containerd같은 런타임이 이를 구동합니다.
Docker는 이 모든 것을 묶어서 버튼 한 번으로 실행할 수 있게 만든 툴일 뿐이죠.
따라서 컨테이너를 깊이 이해하려면 Docker 명령어 외에도 리눅스 커널 기능을 이해하는 것이 중요합니다.
'개발정리 (docker)' 카테고리의 다른 글
| [docker] Docker 네트워크 이해하기: 포트 매핑이 필요한 이유 (0) | 2025.09.25 |
|---|---|
| [docker] 컨테이너 다루기 필수 명령어 모음 (0) | 2025.09.24 |
| [docker] 내 애플리케이션을 Docker 이미지로 만들기 (0) | 2025.09.22 |
| [docker] Dockerfile 제대로 이해하기: 실무에서 자주 쓰는 명령어 정리 (0) | 2025.09.19 |
| [docker] Docker의 장점과 단점 (0) | 2025.09.18 |