[Docker] 컨테이너 기술이 뭔데? 가볍고 빠른 시스템 격리 기술
컨테이너 기술이란?컨테이너 기술은 애플리케이션과 그 실행 환경을 함께 포장해서 배포할 수 있도록 해주는 기술이에요. 쉽게 말하면, "어떤 컴퓨터든 환경이든, 같은 방식으로 내 앱이 잘 돌
intpdev.tistory.com
🐳 Docker는 무엇인가요?
Docker는 애플리케이션을 실행하기 위한 모든 요소를 패키징하고, 이를 어떤 환경에서도 동일하게 실행할 수 있도록 해주는 컨테니어 플랫폼이에요.
조금 더 자세히 말하면, Docker는 컨테이너를 빌드하고, 실행하고, 관리할 수 있는 일련의 도구 모음이에요. 단순히 실행 도구만 제공하는 것이 아니라, 이미지 저장소, API 서버, 네트워크 설정, 볼륨 마운트, 런타임까지 포함돼요.
Docker는 컨테이너를 다루기 쉽게 만든 도구이자, 내부적으로는 여러 핵심 구성 요소들의 조합으로 이뤄져 있습니다.
🐳 Docker의 작동 방식: 컨테이너가 만들어지는 과정
Docker는 다음과 같은 계층 구조로 동작해요:
[사용자 CLI]
↓
[dockerd (Docker 데몬)]
↓
[containerd (컨테이너 관리자)]
↓
[runC (런타임)]
↓
[Linux 커널 (cgroups + namespaces)]
✅ 1) Docker CLI (Command Line Interface): 개발자가 직접 만지는 docker 명령어
- 개발자가 사용하는 docker build, docker run, docker ps 같은 명령어는 이 CLI 계층에서 시작됩니다.
- CLI는 단순히 명령을 받아서 Docker의 핵심 엔진인 dockered(Docker 데몬)에게 API 요청을 전송하는 거예요.
- 즉, CLI는 Docker API의 클라이언트 역할을 합니다.
docker run nginx
→ dockered에게 "nginx 컨테이너 하나 띄워줘"라는 명령을 보냄
✅ 2) dockered (Docker 데몬): Docker의 심장, 중앙 제어 타워
dockered는 Docker 엔진의 메인 프로세스이며, 모든 Docker 동작을 제어해요.
CLI로부터 요청을 받아 다음과 같은 다양한 기능을 처리해요:
- 이미지 빌드 및 다운로드
- 컨테이너 생성, 시작, 정지, 삭제
- 네트워크/볼륨 관리 등을 담당
모든 작업을 dockered가 혼자 하지는 않아요. 실제 컨테이너 실행, 이미지 압축 해제, 파일시스템 스냅샷 생성 등 무거운 일들은 내부적으로 containerd라는 더 경량화된 런타임에 실제 작업을 위임합니다.
→ CLI가 '명령을 요청'하면, dockerd는 이를 '관리하고 분배'해요.
✅ 3) containerd: 컨테이너의 생성, 실행, 중단을 실제로 조작하는 관리자
dockerd의 하위 계층이지만, 독립적으로 실행될 수도 있는 범용 컨테이너 런타임이기도 해요.
현재 CNCF에서 관리하고 있으며, Docker 외에도 Kubernetes, CRI-O 등에서도 사용되는 표준 런타임이에요.
containerd의 주요 역할을 다음과 같아요:
- 컨테이너 생성, 시작, 정지, 삭제
- 이미지의 압축 해제 및 관리
- 네임스페이스, cgroup 등 커널 리소스 세팅
- 스냅샷 관리, 네트워크 설정, 스토리지 연결
→ dockerd는 명령을 내리는 관리자라면, containerd는 그 명령을 받아서 실제 작업을 수행하는 실무자예요.
✅ runC: OCI 기반의 실제 실행기
containerd는 컨테이너를 실행할 때 OCI(Open Container Initiative) 표준에 맞는 런타임을 호출해요. 그 대표 런타임이 바로 runC입니다.
runC는 다음과 같은 작업을 수행해요:
- 리눅스의 cgroups (자원 사용 제한), namespace(환경 격리) 기능을 설정
- 컨테이너 이미지로부터 파일 시스템 생성
- 실행할 명령을 fork/exec 방식으로 리눅스 프로세스 실행
- 모든 설정이 완료된 컨테이너 프로세스를 "진짜로 실행"
🔍 예를 들어, nginx 컨테이너를 실행한다고 하면:
- runC가 cgroup을 설정해서 CPU/Memory를 제한하고
- PID namespace를 설정해서 컨테이너만의 프로세스 공간을 만들고
- root filesystem을 마운트 한 뒤
- /usr/sbin/nginx를 exec()로 실행해요.
→ runC는 "프로세스를 격리된 공간에서 띄우는 런타임"
📌 이렇게 생성된 컨테이너는 일반적인 리눅스 프로세스처럼 동작하지만, 호스트 OS로부터 파일 시스템, 네트워크, PID, 유저 공간 등을 모두 독립적으로 구성해요.
✅ 이 구조 꼭 알아야 하나요?
사실 대부분의 개발자들이 docker run이나 docker build, 네트워크 설정, 볼륨 마운트만 잘 써도 컨테이너 기반 개발은 충분히 할 수 있어요. 그래서 "이런 내부 구조까지 알아야 해?"라고 생각할 수도 있어요.
맞습니다. 사실 컨테이너를 단순히 쓰는 데는 몰라도 괜찮아요.
하지만 아래와 같은 순간에는 이해하는 것이 유용합니다.
- 디버깅 상황
docker ps에는 뜨는데 컨테이너가 실제로 동작하지 않거나, 컨테이너는 종료되었지만 프로세스가 리눅스에 남아 있거나 하는 경우 이런 상황에서 containerd나 runC 레벨에서 무슨 일이 있었는지 파악할 수 있는 능력이 필요해요. - Kubernetes나 클라우드 환경에 진입할 때
Kubernetes에서는 containerd와 CRI(Container Runtime Interface)를 통해 컨테이너를 다루기 때문에, 내부 구조를 알고 있으면 유용합니다. - 보안, 성능 최적화, 커스텀 런타임이 필요할 때
보안이 중요한 환경에서는 runC 대신 보안 강화된 런타임을 사용하는 경우도 있습니다. 이런 설정을 위해선 기본 구조에 대한 이해가 필요해요. 또한 컨테이너의 자원 제한(cgroups), 파일 시스템 격리 방식(mount namespace) 등을 제대로 다뤄야 퍼포먼스 튜닝도 가능해져요.