docker run 명령은 CLI → Docker Daemon → containerd → runc를 거쳐 최종적으로 호스트 커널에서 하나의 프로세스로 실행됩니다. 이 글에서는 명령어 한 줄이 실제 컨테이너로 만들어지기까지의 전체 흐름과 각 구성 요소의 역할을 정리합니다.클라이언트-서버 아키텍처
Docker는 명령을 받는 클라이언트(CLI)와 실제 작업을 수행하는 서버(Daemon)가 분리된 구조입니다. 사용자가 docker run nginx를 입력하면, 아래와 같은 계층을 따라 요청이 전달됩니다.
[사용자]
│ docker run nginx
▼
┌─────────────┐
│ Docker CLI │
└──────┬──────┘
│ REST API 호출
▼
┌─────────────┐
│ dockerd │ ← Docker Daemon
└──────┬──────┘
│ gRPC 호출
▼
┌─────────────┐
│ containerd │ ← 컨테이너 관리 런타임
└──────┬──────┘
│ OCI Runtime Spec 전달
▼
┌─────────────┐
│ runc │ ← 실제 프로세스 생성기
└──────┬──────┘
│ clone() + setns() + cgroups 설정
▼
┌─────────────────────────────────┐
│ Host OS Kernel │ ← 공유 커널
│ ├─ Namespaces(PID, NET, MNT..) │
│ ├─ cgroups(CPU, MEM, IO) │
│ ├─ Capabilities/Seccomp │
│ └─ Syscall Handler │
└─────────────┬───────────────────┘
│ system call
▼
┌─────────────────────────────────┐
│ Container User Space │
│ (프로세스: nginx, bash 등) │
│ - glibc/libc -> syscall wrapper │
│ - 파일/네트워크 요청 │
└─────────────────────────────────┘
이 구조의 핵심 특징은 다음과 같습니다.
- Docker CLI를 통해 Docker Daemon과 통신합니다.
- Docker Daemon은 Docker 컨테이너를 빌드·실행·배포하는 작업을 수행합니다.
- Docker 클라이언트와 데몬은 동일한 시스템에서 실행될 수 있으며, 클라이언트를 원격 데몬에 연결하여 작업을 수행할 수도 있습니다.
- 통신할 때에는 REST API, UNIX 소켓, 또는 네트워크 인터페이스를 통해 통신할 수 있습니다.
docker compose도 Docker 클라이언트의 일종입니다.
구성 요소
1. Docker CLI (Docker Client)
사용자가 docker run, docker build 등의 명령을 Docker Daemon에 전달하는 수단입니다. 하나의 Docker 클라이언트는 여러 데몬과 통신할 수 있습니다.
2. dockerd (Docker Daemon)
CLI로부터 컨테이너 생성·실행 등의 요청을 받아, containerd라는 하위 런타임에 작업을 위임합니다.
3. containerd / runc (OCI 런타임)
컨테이너 스펙(OCI Runtime Spec)에 맞춰 실제 프로세스를 생성합니다. containerd가 컨테이너의 생명주기를 관리하고, runc가 커널 기능을 호출하여 실제 프로세스를 띄우는 역할을 담당합니다.
4. Host OS Kernel (공유 커널)
컨테이너는 OS 전부를 복제하지 않으며, 호스트 커널의 스케줄러·메모리 관리자·네트워크 스택 등을 그대로 사용합니다. 새 프로세스(=컨테이너)는 호스트 커널의 네임스페이스와 cgroups 설정이 적용된 상태로 실행됩니다.
- Namespaces : PID, 네트워크, 마운트, 사용자, IPC 등을 격리
- cgroups : CPU, 메모리, I/O 등 리소스 제한
- Capabilities / Seccomp : 시스템 콜 및 권한 제한
컨테이너 프로세스가 호출하는 시스템 콜은 하나의 호스트 커널에 의해 처리됩니다.
5. Container
컨테이너는 애플리케이션과 해당 사용자 공간(User Space)을 담고 있으며, 커널은 포함하지 않습니다.
uname -r을 실행하면 호스트 커널 버전이 출력됩니다.Docker Desktop
Docker Desktop은 Docker Client, Docker Daemon, Docker Compose, Docker Content Trust, Kubernetes, Credential Helper를 포함하고 있는 통합 애플리케이션입니다.
원격 Docker 데몬에 클라이언트 연결하기
로컬 머신에 설치된 Docker 클라이언트(docker 명령어)를 사용하여 원격 서버에서 실행 중인 Docker 데몬에 연결하고 컨테이너를 관리할 수 있습니다. 가장 일반적인 방법은 DOCKER_HOST 환경 변수를 설정하는 것입니다.
① 원격 서버 설정
원격 서버의 Docker 데몬이 외부 연결을 허용하도록 설정해야 합니다. 보통 /etc/docker/daemon.json 파일에 hosts 설정을 추가하고 데몬을 재시작합니다.
// /etc/docker/daemon.json
{
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
tcp://0.0.0.0:2376)을 구성해야 합니다.② 클라이언트(로컬 머신) 설정
터미널에서 DOCKER_HOST 환경 변수를 원격 서버의 주소와 포트로 설정합니다.
# Linux / macOS
export DOCKER_HOST="tcp://<REMOTE_SERVER_IP>:2375"
# Windows (PowerShell)
$env:DOCKER_HOST = "tcp://<REMOTE_SERVER_IP>:2375"
환경 변수 설정 후 docker ps, docker images 같은 명령어를 실행하면, 이제 로컬이 아닌 원격 서버의 데몬에 전달되어 그곳의 컨테이너와 이미지를 보여줍니다.
그 외 방법
- -H 플래그 : 환경 변수 설정 없이 일회성으로 원격 데몬에 명령을 보낼 때 사용합니다. 예:
docker -H tcp://<IP>:2375 ps - Docker Context : 여러 데몬(로컬·원격·클라우드)을 자주 전환할 때 유용합니다.
docker context create로 연결 정보를 저장하고docker context use <NAME>으로 전환합니다.
- ① Docker 란 무엇인가?
- ② Docker 아키텍처 — CLI부터 커널까지
- ③ Docker 이미지 빌드와 배포 — Dockerfile, 레이어, 멀티스테이지
- ④ Docker 실무 — 명령어와 컨테이너 동작 원리