학습 목표
Docker CLI와 containerd·runc 등 OCI 런타임 계층을 설명할 수 있다.
Linux namespace와 cgroup이 격리·자원 제한에 어떻게 쓰이는지 설명할 수 있다.
capabilities, rootless, 최소 권한 이미지로 공격 면을 줄이는 방법을 설명할 수 있다.
컨테이너가 VM만큼 격리되지 않는다는 전제에서 보안을 설계할 수 있다.
문제 상황
docker run한 줄이면 되는데, 컨테이너 안 프로세스가 호스트와 뭐가 다른지 모른다ps를 호스트에서 보면 컨테이너 PID도 보인다
--privileged로 문제를 풀었다가 호스트 탈출 이슈를 본다- 컨테이너 = 가벼운 VM이 아니다
- 이미지가
root로 돌고,latest베이스에 쓸데없는 패키지가 잔뜩- CVE 스캔할 때마다 수백 건 경고
- 메모리 제한 없이 배포했다가 OOM으로 노드 전체가 흔들린다
Dockerfile·run 옵션을 봤다. 이번 편은 엔진 아래—커널이 프로세스를 어떻게 감싸는지와 보안 기본값이다.
1. OCI 런타임 스택
docker run은 단일 바이너리가 아니다. 이미지 풀 → 스냅샷 → 프로세스 생성을 여러 계층이 나눈다.

| 계층 | 역할 |
|---|---|
| Docker CLI | 사용자 명령 (run, build, push) |
| dockerd | API, 이미지·네트워크·볼륨 관리 |
| containerd | 컨테이너 생명주기, 이미지 레이어 스냅샷 |
| runc (OCI runtime) | config.json대로 namespace·cgroup 설정 후 프로세스 exec |
| Linux kernel | 실제 격리·자원 제한 |
- Kubernetes도 노드에서 containerd/CRI-O + runc 조합이 흔하다
- 표준은 OCI (Open Container Initiative) — 이미지·런타임 스펙
2. Namespace — 무엇을 가리는가
Namespace는 프로세스가 보는 시스템 뷰를 분리한다. OS 시리즈의 프로세스·주소 공간과 같은 축.

| Namespace | 격리 대상 | 컨테이너에서 |
|---|---|---|
| PID | 프로세스 ID | 컨테이너 안 PID 1 = 앱, 호스트 PID는 다름 |
| NET | 네트워크 스택 | 자체 eth0, IP, 포트 공간 |
| MNT | 마운트 트리 | 이미지 레이어 + writable layer |
| UTS | hostname | --hostname |
| IPC | 공유 메모리·세마포어 | 컨테이너 간 기본 분리 |
| USER | UID/GID 매핑 | rootless·user namespace |
- 격리는 뷰 분리 — 커널은 공유
--privileged는 대부분의 namespace·device 제한을 풀어버림 → 최후 수단
3. Cgroup — 자원 한도
Cgroup은 CPU·메모리·I/O 등 사용량 상한과 accounting.
docker run -d --memory=512m --cpus=1.5 my-app:1.0
| 리소스 | 옵션 예 | 없을 때 |
|---|---|---|
| 메모리 | --memory, --memory-swap |
호스트 RAM까지 사용 → OOM |
| CPU | --cpus, --cpu-shares |
호스트 CPU 독점 가능 |
| PID | --pids-limit |
fork bomb에 취약 |
- K8s의
requests/limits도 결국 cgroup으로 적용 - limit만 주고 request 없으면 스케줄링·노이즈 이웃 문제 (K8s 편에서 확장)
4. Capabilities와 root
Linux root는 모든 권한. 컨테이너는 기본적으로 일부 capability만 부여한다.

| 기법 | 설명 |
|---|---|
| Drop capabilities | NET_BIND_SERVICE만 필요하면 나머지 제거 |
| Non-root user | Dockerfile USER app — 파일·소켓 권한 설계 필요 |
| Read-only rootfs | docker run --read-only + tmpfs for /tmp |
| seccomp / AppArmor | syscall·프로파일 제한 (엔진 기본 프로파일) |
| Minimal base image | distroless, alpine — 공격 면 축소 |
FROM python:3.12-slim
RUN useradd -m app
USER app
WORKDIR /home/app
COPY --chown=app:app . .
CMD ["python", "main.py"]
- root 컨테이너 + 취약점 = 호스트 침해 가능성 상승
--privileged,hostPID,hostNetwork는 의도적 예외만
5. Rootless Docker
Rootless — 데몬·컨테이너가 비 root 사용자로 동작. user namespace로 컨테이너 root를 unprivileged UID에 매핑.
| 일반 모드 | Rootless | |
|---|---|---|
| 데몬 | root | 일반 사용자 |
| 컨테이너 내 root | 실제 root에 가까움 | user ns 매핑 |
| 포트 1024 미만 | 허용(권한 있으면) | 추가 설정 필요 |
- 개발·CI 워크스테이션에서 호스트 보호에 유리
- 프로덕션은 보통 rootful 노드 + Pod Security (K8s)로 정책화
6. 이미지·공급망 보안
- 고정 태그 —
python:3.12-slim또는 digest pin - 멀티 스테이지 — 빌드 도구를 런타임 이미지에 넣지 않음
- 스캔 — Trivy, Docker Scout 등으로 CVE 확인
- 서명 — cosign 등으로 이미지 출처 검증 (CI/CD 편)
컨테이너 보안은 런타임 설정 + 이미지 내용 + 권한 최소화 세 축이다.
7. 정리
docker run끝은 runc + kernel — namespace로 뷰 분리, cgroup으로 자원 제한- 컨테이너는 프로세스 격리이지 VM이 아니다 —
--privileged남용 금지 - capabilities drop, non-root, read-only, 최소 이미지가 기본선
- 다음은 오케스트레이션 — Kubernetes가 이 단위를 클러스터로 다룬다
다음에 다룰 것
- Kubernetes 개요
- control plane, worker, 선언적 API, desired state
해당 내용은 Docker 공식 문서(https://docs.docker.com) 및 OCI runtime-spec 을 기반으로 합니다.
'플랫폼, 데브옵스와 클라우드' 카테고리의 다른 글
| Pod와 Deployment (0) | 2026.06.23 |
|---|---|
| Kubernetes 개요 (0) | 2026.06.22 |
| Docker 기초 (0) | 2026.06.20 |
| 컨테이너란 무엇인가 (0) | 2026.06.19 |
| 플랫폼 오리엔테이션 (0) | 2026.06.18 |