Docker Architecture: 클라이언트-서버 모델 이해하기
Docker는 클라이언트-서버 아키텍처를 기반으로 설계되었습니다. 이 구조는 크게 세 가지 주요 구성 요소로 이루어져 있습니다.

- Docker 클라이언트: 사용자가 명령어를 입력하는 인터페이스
- Docker 데몬(서버): 컨테이너를 관리하고 실행하는 백그라운드 서비스
- Docker 레지스트리: 도커 이미지를 저장하고 공유하는 저장소 (예: Docker Hub)
사용자가 직접 컨테이너와 상호작용하지 않고, Docker 클라이언트를 통해 Docker 데몬에 요청을 보내면 데몬이 실제 작업을 수행하는 방식으로 작동합니다.
Docker 데몬과 RESTful API 통신
Docker 데몬(dockerd)은 Docker 시스템의 핵심으로, 다음과 같은 중요한 역할을 수행합니다.
- 컨테이너 생성, 실행, 중지, 삭제 등의 라이프사이클 관리
- 이미지 빌드 및 관리
- 볼륨 및 네트워크 관리
- REST API 제공을 통한 외부 시스템과의 통신
Docker 데몬은 RESTful API를 통해 통신합니다. 이는 HTTP 프로토콜 기반의 API로, JSON 형식으로 데이터를 주고받습니다.
Docker CLI: 사용자와 API 사이의 번역기
Docker CLI(Command Line Interface)는 사용자가 입력한 간단한 명령어를 Docker 데몬의 RESTful API 요청으로 변환해주는 '번역기' 역할을 합니다.
1. 사용자가 docker ps 명령어를 입력
2. Docker CLI는 이를 GET /containers/json API 요청으로 변환
3. Docker 데몬에 전송
4. 받은 JSON 응답을 테이블 형태로 가공하여 사용자에게 표시
사용자(외국어를 모르는 사람)는 CLI(통역사)를 통해 Docker 데몬(외국어를 사용하는 사람)과 의사소통을 할 수 있게 됩니다.
만약 도커 컨테이너 목록을 조회한다고 가정하고 RestfulAPI와 CLI의 방식은 다음과 같습니다.
RestfulAPI
# 요청
curl --unix-socket /var/run/docker.sock -X GET http://localhost/containers/json
# 응답
[
{
"Id": "8dfafdbc3a40c5cec82af974966805c6810b73f1d793e0afb25a8349859c5d70",
"Names": ["/boring_feynman"],
"Image": "nginx",
"ImageID": "sha256:4bb46517cac3cece8206ebbf74d1d53d184b630e3dde3406812811bf4151b8ac",
"Command": "nginx -g 'daemon off;'",
"Created": 1628632643,
"Ports": [{"PrivatePort": 80, "PublicPort": 8080, "Type": "tcp", "IP": "0.0.0.0"}],
"Labels": {},
"State": "running",
"Status": "Up 2 hours",
"HostConfig": {"NetworkMode": "default"},
"NetworkSettings": {"Networks": {"bridge": {"IPAddress": "172.17.0.2"}}},
"Mounts": []
}
]
CLI
# 요청
docker ps
# 응답
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8dfafdbc3a40 nginx "nginx -g 'daemon of…" 2 hours ago Up 2 hours 0.0.0.0:8080->80/tcp boring_feynman
명령어의 복잡성과 응답의 가독성을 비교해을 때, 도커에서 제공하는 CLI를 사용하는 것이 더 효율적이라는 것을 알 수 있습니다.
Docker 내부 구성 요소와 컨테이너 런타임
Docker 데몬은 직접 컨테이너를 실행하지 않고, 다음과 같은 구성 요소들을 사용합니다:
containerd
containerd는 Docker와 runc 사이의 중간 계층으로, 다음 역할을 담당합니다:
- 이미지 풀링, 푸싱, 관리
- 컨테이너 실행 관리
- 스토리지 관리
- 네트워크 인터페이스 관리
Docker 데몬이 containerd에 gRPC를 통해 명령을 전달하면, containerd는 이 명령을 처리하고 필요에 따라 runc를 호출합니다.
runc
runc는 OCI(Open Container Initiative) 표준을 준수하는 저수준 컨테이너 런타임입니다.
- Linux 커널의 기능(네임스페이스, cgroups)을 사용하여 실제로 컨테이너를 생성하고 실행
- 컨테이너의 리소스 격리와 제한을 설정
- 컨테이너 내부의 프로세스 실행
예를 들어, docker run -p 80:80 nginx 명령어가 실행되면 다음과 같은 과정이 일어납니다.
1. Docker CLI: 명령어를 해석하고 /containers/create API 요청으로 변환
2. Docker 데몬:
- API 요청을 받아 처리
- nginx 이미지 확인 / 이미지가 없다면 Docker Hub에서 다운로드
- containerd에 컨테이너 생성 요청 전달
3. containerd:
- 이미지 레이어 준비
- 컨테이너 스펙 생성
- runc를 호출하여 컨테이너 생성 요청
4. runc:
- 네임스페이스와 cgroups를 설정하여 컨테이너 환경 준비
- nginx 프로세스를 격리된 환경에서 시작
- 컨테이너의 리소스 제한 적용
5. 네트워크 설정:
- Docker 데몬은 호스트의 80번 포트를 컨테이너의 80번 포트로 매핑
전체 과정은 사용자에게는 단일 명령어로 추상화되어 보이지만, 내부적으로는 여러 구성 요소와 복잡한 상호작용을 통해 실행되고 있음을 알 수 있습니다.
결론적으로, Docker의 클라이언트-서버 아키텍처와 RESTful API 기반 통신 모델은 모듈성, 확장성, 유연성의 완벽한 조합을 보여준다고 생각합니다. 사용자는 간단한 CLI 명령어로 복잡한 컨테이너 작업을 수행할 수 있고, 다양한 도구와 애플리케이션이 Docker API를 통해 Docker 환경과 통합될 수 있습니다.
'Infra' 카테고리의 다른 글
| [K8S] 왜 실무에서는 쿠버네티스를 많이 쓸까? (0) | 2025.05.19 |
|---|---|
| [K8S] K8S 설치하기 (2) | 2025.05.07 |
| [K8S] Linux, Container, Orchestration (0) | 2025.05.06 |
| Docker 이미지: 가상화의 핵심 요소 (0) | 2025.04.28 |
| Docker 개념 정리: 컨테이너 가상화 기술의 이해 (0) | 2025.04.22 |
댓글