도커와 containerd — 컨테이너 런타임의 탄생과 진화
오늘날 클라우드와 백엔드 개발에서 컨테이너는 공기나 물처럼 당연한 기본 기술이 되었습니다. 우리는 매일 docker build, docker run 명령어를 입력하고, 클라우드에서는 쿠버네티스가 수백 개의 컨테이너를 자동으로 띄워줍니다.
하지만 많은 엔지니어가 도커(Docker)와 컨테이너를 동의어로 생각하거나, 쿠버네티스 1.24 버전에서 발표되었던 “도커 지원 중단(Dockershim 제거)” 소식에 혼란을 겪었습니다. “도커를 안 쓰면 우리 이미지는 어떻게 빌드하지?”, “containerd는 도커와 무슨 관계인가?”와 같은 질문들이 대표적입니다.
리눅스 커널의 격리 메커니즘에서 출발하여, 도커가 가져온 혁신, 그리고 거대한 모놀리스였던 도커가 OCI 표준과 containerd로 분리되어 현대 인프라의 주춧돌이 되기까지의 런타임 진화 과정을 살펴봅니다.
1. 컨테이너는 원래 새로운 기술이 아니었다
컨테이너라는 개념은 하늘에서 갑자기 떨어진 발명품이 아닙니다. 본질적으로 컨테이너는 “리눅스 커널의 여러 격리 기능을 조합해 만든 독립된 프로세스” 에 불과합니다.
과거부터 리눅스와 유닉스에는 프로세스를 독립된 공간에 가두기 위한 여러 기술이 존재했습니다:
- chroot (1979년): 프로세스가 바라보는 루트 디렉터리(
/)의 위치를 변경하여 파일 시스템의 특정 하위 폴더 밖으로 나가지 못하게 격리했습니다. 흔히 chroot를 이용한 jail 이라 부르며, 파일 시스템 격리의 시초가 되었습니다. - 리눅스 네임스페이스 (Namespaces): 프로세스가 바라보는 시스템 자원의 ‘시야’를 분리합니다.
PID: 프로세스 번호 체계를 분리 (컨테이너 내부에서는 자신이 1번 프로세스인 것처럼 보임)NET: 네트워크 인터페이스, 라우팅 테이블, 포트 공간 분리MNT: 파일 시스템 마운트 지점 분리IPC: 프로세스 간 통신 격리UTS: 호스트네임 분리USER: 사용자 UID/GID 매핑 분리
- cgroups (Control Groups, 2007년 구글이 기여): 프로세스가 사용할 수 있는 물리적 하드웨어 리소스의 ‘양’을 제한합니다.
- CPU 사용량 제한 및 코어 고정
- 메모리 사용 한계치(OOM 방지) 및 스왑 제어
- 디스크 I/O 대역폭 제한
이 세 가지(chroot의 후예인 피벗 루트, 네임스페이스, cgroups)를 묶으면, 호스트 OS 커널 하나 위에서 완전히 격리된 별도의 가상 운영체제처럼 동작하는 프로세스 격리 공간이 완성됩니다. 2008년 등장한 LXC(LinuX Containers) 가 바로 이 방식의 대표 주자였습니다.
하지만 LXC 시절의 컨테이너는 시스템 관리자들의 전유물이었습니다. 설정이 까다롭고, 네트워크 구성이 복잡했으며, “내 서버에서는 도는데 동료 서버에서는 왜 안 돌지?”라는 재현성 문제를 완전히 해결하지 못했습니다.
💡 프로세스 번호(PID)가 분리되면 호스트 OS에서는 어떻게 보일까?
PID 네임스페이스의 동작 방식을 보면 “컨테이너의 본질”이 무엇인지 명확하게 드러납니다.
만약 우리가 도커 컨테이너로 Nginx 웹 서버를 띄웠다고 가정해 보겠습니다:
-
컨테이너 내부의 시선: 컨테이너 안에 들어가
ps -ef를 실행해 보면, Nginx 마스터 프로세스가 PID 1 번으로 보입니다.# 컨테이너 내부 터미널 UID PID PPID CMD root 1 0 nginx: master process /usr/sbin/nginx컨테이너 내부에서는 오직 자기 자신과 자식 프로세스들만 보이며, 호스트 OS나 다른 컨테이너의 프로세스는 완전히 가려집니다. 컨테이너 입장에서는 자기가 마치 독립된 머신의 유일한 1번 프로세스(init)인 양 인식하는 것입니다.
-
호스트 OS(외부)의 시선: 하지만 호스트 리눅스 머신의 터미널에서
ps -ef | grep nginx를 쳐보면 완전히 다른 결과가 나옵니다:# 호스트 OS 터미널 UID PID PPID CMD root 48215 1832 nginx: master process /usr/sbin/nginx호스트 OS 커널의 관점에서는 이 프로세스가 결코 별도의 가상머신이 아닙니다. 호스트에서 실행 중인 수많은 평범한 리눅스 프로세스 중 하나(예: PID 48215) 에 불과합니다.
이 사실은 컨테이너에 대해 매우 중요한 세 가지 통찰을 줍니다:
- 하나의 프로세스, 두 개의 번호표: 리눅스 커널의 프로세스 관리 구조체(
task_struct)는 프로세스가 속한 네임스페이스 트리에 따라 서로 다른 PID 번호를 매핑합니다. 이 프로세스는 호스트 네임스페이스에서는 48215번, 컨테이너 네임스페이스에서는 1번이라는 두 개의 번호표를 동시에 달고 달리는 것입니다. - 컨테이너는 가상머신(VM)이 아니다: 가상머신은 하이퍼바이저 위에 별도의 게스트 OS 커널이 완전히 독립된 메모리 공간을 부팅하지만, 컨테이너는 “호스트 OS 커널 위에서 그냥 실행 중인 일반 프로세스에 네임스페이스라는 안경을 씌워 시야만 가려둔 것” 입니다.
- 호스트에서의 직접 제어: 호스트 OS의 루트 사용자는 컨테이너 내부로 들어가지 않고도 호스트 터미널에서
kill -9 48215를 실행해 컨테이너의 핵심 프로세스를 즉시 강제 종료시킬 수 있습니다. PID 1이 종료되면 컨테이너의 PID 네임스페이스 전체가 파괴되므로 컨테이너도 즉시 종료(Stop) 상태가 됩니다.
2. 물류의 혁신에서 배운 지혜: 표준 규격 컨테이너
도커의 이름과 고래 로고 위에 실린 네모난 박스들은 결코 우연히 지어진 것이 아닙니다. 20세기 중반 글로벌 무역의 판도를 바꾼 ‘해상 운송용 규격 컨테이너’ 의 역사에서 그대로 착안한 것입니다.
1950년대 이전의 전 세계 항구는 혼돈 그 자체였습니다. 면화 자루, 나무 궤짝, 와인 통, 자동차 부품 등 제각각인 모양과 크기의 화물을 부두 노동자(Dockworkers)들이 일일이 손으로 들고 날라 배 안쪽에 차곡차곡 쌓아야 했습니다(이를 개별 화물 운송, Break-bulk cargo라고 불렀습니다). 배 한 척을 싣고 내리는 데 며칠에서 몇 주가 걸렸고, 하역 과정에서 화물이 파손되거나 도난당하는 일도 빈번했습니다.
1956년 미국의 사업가 말콤 맥린(Malcolm McLean)이 도입한 표준 규격 컨테이너(Intermodal Shipping Container) 는 전 세계 물류에 기적을 일으켰습니다:
- 화물 내용물과 운송 수단의 분리: 항구의 크레인은 박스 안에 든 것이 사과인지 철강인지 알 필요가 없습니다. 모서리의 표준 규격 홈만 집어 올리면 그만이었습니다.
- 복합 일관 운송(Intermodal Freight): 배에서 내린 컨테이너는 박스를 뜯지 않고 그대로 기차나 대형 트럭에 옮겨 실을 수 있었습니다.
- 비용과 시간의 극적인 절감: 하역 비용은 90% 이상 폭락했고, 운송 시간은 획기적으로 줄어들어 오늘날의 글로벌 공급망과 세계화를 가능하게 만든 주역이 되었습니다.
도커는 바로 이 물류 혁명을 디지털 소프트웨어 세계에 그대로 재현했습니다.
도커 이전의 소프트웨어 배포는 제각각인 화물을 싣는 부두와 같았습니다. “파이썬 3.8 환경, 특정 버전의 glibc, 데이터베이스 드라이버, 호스트 OS 환경 변수…” 엔지니어는 서버마다 들어가서 이 의존성들을 일일이 손으로 설치하고 조립해야 했습니다.
도커는 애플리케이션 코드와 실행에 필요한 모든 런타임 의존성을 ‘도커 이미지’라는 표준 규격 박스 에 통째로 밀봉했습니다. 이제 서버 인프라(로컬 PC든, AWS든, 온프레미스 베어메탈이든)는 안에 든 것이 자바인지 파이썬인지 상관없이, 똑같은 표준 크레인(docker run)으로 집어 올려 실행하기만 하면 되었습니다.
3. 도커의 진짜 혁신: 런타임이 아니라 ‘패키징과 UX’
2013년 솔로몬 하익스(Solomon Hykes)가 이끄는 닷클라우드(dotCloud) 팀이 오픈소스로 공개한 도커(Docker) 는 업계를 단숨에 뒤흔들었습니다.
도커가 성공한 이유는 밑단의 리눅스 격리 기술을 새로 만들어서가 아니었습니다. 초기 도커는 실제로 LXC를 백엔드로 그대로 사용했습니다. 도커가 만든 진정한 혁명은 개발자 경험(Developer Experience)과 이미지 패키징 이었습니다:
- Dockerfile: 인프라 구성을 마치 코드처럼 몇 줄의 텍스트로 정의할 수 있게 되었습니다.
- 유니온 파일 시스템(UnionFS) 기반의 계층형 이미지: 베이스 OS 레이어 위에 라이브러리 레이어, 애플리케이션 레이어를 층층이 쌓아 불필요한 중복 저장을 없애고 전송 속도를 극대화했습니다.
- Docker Hub: 누구나
docker pull redis,docker pull nginx만 입력하면 검증된 환경을 수 초 만에 내려받아 실행할 수 있는 글로벌 배포 유통망을 만들었습니다. - 단순하고 직관적인 CLI: 복잡한 시스템 콜이나 네트워크 설정 대신
docker build,docker run,docker ps몇 가지 명령어만으로 컨테이너의 모든 라이프사이클을 직관적으로 제어할 수 있게 했습니다.
“내 컴퓨터에서는 잘 돌아가는데요”라는 소프트웨어 업계의 오랜 고질병이 도커 이미지라는 불변의 단일 아티팩트(Immutable Artifact)로 완벽히 해결되는 순간이었습니다.
4. 거대해진 도커와 OCI(Open Container Initiative) 표준화
초기 도커는 하나의 거대한 데몬 프로세스(dockerd)였습니다. 이 단일 데몬 안에서:
- 이미지 빌드
- 도커 레지스트리 통신
- 네트워크(브리지, IP 할당) 설정
- 볼륨 마운트 관리
- 리눅스 시스템 콜을 통한 컨테이너 프로세스 포크
등 모든 일을 도맡아 처리했습니다.
하지만 도커의 인기가 폭발하면서 기업들의 요구사항이 쏟아졌습니다. “우리는 도커의 이미지 포맷은 좋은데 다른 오케스트레이터를 쓰고 싶다”, “도커 데몬이 죽으면 실행 중이던 수백 개의 컨테이너까지 같이 죽어버리는 단일 장애점(SPOF) 구조는 위험하다”는 비판이 제기되었습니다.
특히 코어OS(CoreOS) 같은 경쟁 진영에서는 rkt(로켓)이라는 독자적인 컨테이너 런타임을 출시하며 컨테이너 표준을 두고 충돌하기 시작했습니다.
파편화 위기에 직면하자 구글, 도커, 레드햇, 마이크로소프트 등 주요 테크 기업들은 2015년 리눅스 재단 산하에 OCI(Open Container Initiative) 라는 표준 기구를 설립하고, 컨테이너 규격을 크게 두 가지로 명세화했습니다:
- 이미지 규격 (Image Spec): 컨테이너 이미지를 어떤 파일 구조(tar, json 메타데이터, 레이어 구조)로 만들어야 하는지에 대한 표준
- 런타임 규격 (Runtime Spec): 압축이 풀린 이미지 파일 시스템(RootFS)과 환경설정(
config.json)을 받아서 실제 리눅스 프로세스로 실행하는 방법에 대한 표준
그리고 도커는 자사 코드베이스에서 리눅스 커널에 직접 맞닿아 프로세스를 띄우는 핵심 로우레벨 코드를 OCI 런타임 레퍼런스 구현체로 기증했습니다. 이것이 바로 오늘날의 **runc**입니다.
5. containerd의 탄생과 모듈화
runc는 단지 “이미 준비된 파일 시스템을 프로세스로 띄우고 종료하는” 극도로 가벼운 CLI 도구입니다. 네트워크를 설정하거나, 레지스트리에서 원격 이미지를 다운로드하거나, 컨테이너 프로세스의 상태를 백그라운드에서 감시(Supervision)하는 기능은 의도적으로 제외되어 있습니다.
그렇다면 runc 위에서 이미지 전송, 스토리지 스냅샷 관리, 프로세스 감시를 담당할 전문적인 고수준 런타임이 필요했습니다.
도커사는 2017년, 자사 엔진에서 이 핵심 코어 레이어를 떼어내 **containerd**라는 독립 프로젝트로 분리하고, 이를 CNCF(Cloud Native Computing Foundation)에 기증했습니다.
flowchart TD
CLI["<b>클라이언트 계층</b><br/>Docker CLI / Kubernetes kubelet"]
CONTAINERD["<b>고수준 런타임 (High-Level): containerd</b><br/>• 원격 이미지 풀링 & 압축 해제<br/>• 스냅샷 기반 스토리지 레이어 관리<br/>• 컨테이너 수명주기 총괄"]
SHIM["<b>containerd-shim</b><br/>런타임 데몬 재시작 시에도 프로세스 IO 유지 (무중단)"]
RUNC["<b>저수준 런타임 (Low-Level / OCI): runc</b><br/>• OCI 표준 Runtime Spec 준수<br/>• 리눅스 커널 시스템 콜 (clone, setns, unshare, cgroups)"]
APP["<b>격리된 애플리케이션 컨테이너 프로세스</b>"]
CLI -->|"gRPC API 명령"| CONTAINERD
CONTAINERD -->|"shim 프로세스 포크"| SHIM
SHIM -->|"OCI 명세 전달 및 기동"| RUNC
RUNC -->|"호스트 커널 격리 공간 생성"| APP
이 분리 덕분에 결정적인 구조적 개선이 이루어졌습니다:
- 무중단 업그레이드: 도커 데몬이나
containerd를 업그레이드하거나 재시작해도, 중간의containerd-shim이 프로세스의 파일 디스크립터(STDIN/STDOUT/STDERR)를 쥐고 있기 때문에 실행 중인 애플리케이션 컨테이너는 중단 없이 계속 동작할 수 있게 되었습니다.
6. 쿠버네티스의 Dockershim 제거 사건의 진실
2020년 말, 쿠버네티스 커뮤니티는 커다란 발표를 했습니다. “v1.20부터 Dockershim을 deprecated 처리하고, v1.24에서 완전히 제거한다”는 소식이었습니다.
당시 많은 이들이 “이제 도커는 망했다”, “Dockerfile을 다 버리고 새로 짜야 하느냐”며 불안해했습니다. 하지만 이는 컨테이너 생태계의 런타임 표준화 과정을 이해하지 못한 데서 온 해프닝이었습니다.
왜 Dockershim이 필요했고, 왜 버렸을까?
쿠버네티스의 각 노드에는 에이전트인 kubelet이 실행됩니다. 쿠버네티스는 특정 벤더에 종속되지 않고 다양한 런타임을 갈아 끼울 수 있도록 CRI(Container Runtime Interface) 라는 표준 gRPC 인터페이스를 정의했습니다.
문제는 도커 엔진(dockerd)이 CRI 표준이 나오기 전부터 존재하던 제품이라 CRI를 구현하지 않았다는 점이었습니다. 그래서 쿠버네티스 개발팀은 울며 겨자 먹기로 도커 API와 CRI를 중계해 주는 통역기인 **dockershim**을 쿠버네티스 소스코드 내부에 직접 짜 넣어서 유지보수해야 했습니다.
이 과정에서 극심한 낭비가 발생했습니다:
kubelet이 CRI 명령을 내리면,dockershim이 이를 Docker REST API로 번역합니다.dockerd는 그 명령을 받아서 다시 내부의containerd를 호출합니다.- 정작 쿠버네티스는 도커의 볼륨 관리, 스웜 클러스터링, 빌드 엔진 같은 무거운 기능이 전혀 필요 없는데도 메모리와 CPU를 계속 낭비해야 했습니다.
게다가 containerd는 이미 자체적으로 CRI 플러그인을 내장하여 kubelet과 직접 대화할 수 있는 준비가 끝나 있었습니다.
flowchart TD
subgraph PRESENT["<b>현재: 간결해진 CRI 직통 구조 (v1.24~)</b>"]
direction TB
K2["<b>kubelet</b>"]
CD2["<b>containerd</b><br/>(CRI 플러그인 내장)"]
SHIM2["<b>containerd-shim</b><br/>(무중단 관리)"]
R2["<b>runc</b>"]
C2["<b>컨테이너</b>"]
K2 -->|"CRI 표준 gRPC 직통"| CD2
CD2 --> SHIM2 --> R2 --> C2
end
subgraph PAST["<b>과거: 비효율적인 이중 통역 구조 (Dockershim)</b>"]
direction TB
K1["<b>kubelet</b>"]
D1["<b>dockershim</b><br/>(임시 통역기 / 오버헤드)"]
DD1["<b>dockerd (도커 데몬)</b><br/>(불필요 기능 점유)"]
CD1["<b>containerd</b>"]
R1["<b>runc</b>"]
C1["<b>컨테이너</b>"]
K1 -->|"CRI 호출"| D1
D1 -->|"REST API 번역"| DD1
DD1 --> CD1 --> R1 --> C1
end
쿠버네티스는 중간 다리였던 불필요한 통역기(dockershim과 dockerd)를 걷어내고, 진정한 엔진이었던 containerd와 직통 전화선을 연결한 것뿐이었습니다.
개발자에게 미친 영향은?
- Zero: 개발자가 로컬에서
docker build로 만든 이미지는 OCI 규격을 100% 만족하므로, containerd 기반의 쿠버네티스 클러스터에서 한 줄의 수정도 없이 완벽하게 실행됩니다. - 서버 환경에서는 군더더기 없는
containerd런타임의 가벼움과 안정성을 누리고, 개발자는 로컬에서 편한 도구를 사용하면 되었습니다.
7. ‘Docker’가 아니라 ‘Docker Desktop’의 유료화, 그리고 대안 도구들의 현실적 한계
서버 인프라에서 containerd로의 표준화가 진행되던 2021년 8월, 개발자들의 로컬 PC 환경에서도 커다란 혼란이 발생했습니다. 흔히 “도커가 유료화되었다”고 알려진 사건입니다.
하지만 엄밀히 말해 이는 ‘Docker(엔진)‘의 유료화가 아니라 ‘Docker Desktop’이라는 특정 GUI/가상화 번들 패키지의 유료화 였습니다.
유료화 정책의 실체와 오해 바로잡기
오케스트레이션 전쟁 이후 개발자 도구 중심으로 체질을 개선하던 도커 사(Docker Inc.)는 막대한 Docker Hub 인프라 비용과 개발비를 감당하기 위해 비즈니스 모델을 변경했습니다:
- 무료 대상: 개인 사용자, 교육 기관, 비상업용 오픈소스 프로젝트, 그리고 직원 250명 미만 & 연간 매출 1,000만 달러(약 130억 원) 미만의 소기업
- 유료 대상: 위 기준을 초과하는 중견·대기업의 업무용 환경 (Docker Pro, Team, Business 구독 필요)
중요한 점은 **리눅스 서버에서 돌아가는 오픈소스 도커 엔진(Moby 프로젝트 기반의 dockerd, containerd, runc)과 CLI는 지금도 100% 무료 오픈소스(Apache 2.0)**라는 사실입니다. 유료화된 것은 macOS와 Windows에서 리눅스 커널 가상머신(HyperKit, WSL2)을 백그라운드로 띄우고 GUI 대시보드와 네트워킹 편의 기능을 제공하던 ‘Docker Desktop’이라는 독점(Proprietary) 클라이언트 소프트웨어 뿐이었습니다.
대안 소프트웨어들의 장점과 현실적인 단점
라이선스 비용과 감사(Audit) 리스크를 피하려는 기업들이 늘어나면서 여러 대안 도구들이 주목받았습니다. 하지만 실무에 도입해 보면 Docker Desktop의 “그냥 깔면 아무 문제 없이 돌아가는(Just works)” 압도적인 완성도 를 대체하는 과정에서 각 도구마다 뚜렷한 단점과 마찰(Friction)에 직면하게 됩니다.
1. Podman & Podman Desktop (Red Hat)
- 장점: 데몬이 필요 없는 데몬리스(Daemonless) 와 루트 권한이 필요 없는 루트리스(Rootless) 아키텍처로 엔터프라이즈 보안 기준을 완벽히 충족합니다. 완전한 오픈소스(Apache 2.0)입니다.
- 단점 및 한계:
- 도커 소켓(
docker.sock) 호환성 문제: 많은 개발 도구(Testcontainers, IDE 도커 플러그인, CI/CD 스크립트)가/var/run/docker.sock에 의존합니다. Podman이 소켓 에뮬레이션을 지원하지만, 권한 문제나 소켓 미인식 버그로 인해 설정에 많은 시간을 낭비하기 쉽습니다. - Rootless 모드의 권한 꼬임: 호스트와 컨테이너 간 UID/GID 매핑(
subuid/subgid)이 복잡하여 로컬 볼륨 마운트 시 파일 쓰기 권한 오류가 빈번히 발생하며, 1024 이하의 특권 포트 바인딩에 제약이 따릅니다. - 컴포즈 파편화:
docker-compose대체제로podman compose(v2 플러그인)와 파이썬 기반의podman-compose가 혼재되어 일부 복잡한 컴포즈 문법에서 예기치 못한 에러가 발생합니다.
- 도커 소켓(
2. Rancher Desktop (SUSE)
- 장점: 완전한 오픈소스(Apache 2.0)이며,
dockerd(Moby)와containerd(nerdctl)중 런타임을 자유롭게 선택할 수 있습니다. 경량 로컬 쿠버네티스(k3s)가 내장되어 있습니다. - 단점 및 한계:
- 무거운 리소스 소모: 가상머신과 함께 k3s 클러스터가 기본적으로 돌아가다 보니 Docker Desktop 못지않게, 혹은 그 이상으로 CPU와 메모리를 많이 점유합니다.
- 안정성 이슈: 백엔드 VM 기동 실패, 가상화 드라이버 충돌, UI 반응 지연 등의 잔버그가 종종 보고되어 개발 머신의 안정성이 중요한 환경에서는 호불호가 갈립니다.
3. OrbStack (macOS 전용)
- 장점: macOS 환경에서 경이적인 최적화를 보여줍니다. 네이티브 Swift 기반으로 제작되어 Docker Desktop 대비 부팅이 번개처럼 빠르고(2초 이내), 메모리와 배터리 소모가 극도로 적으며 파일 I/O 속도가 압도적입니다.
- 단점 및 한계:
- 오픈소스가 아닌 상용 소프트웨어: Docker Desktop의 라이선스 비용을 피하려던 기업에게는 대안이 되지 못합니다. 개인에게는 무료지만 기업 업무 환경에서는 결국 유료 라이선스를 구매 해야 하므로 벤더 종속만 바뀌는 셈입니다.
- macOS 전용: Windows나 Linux를 사용하는 팀원들과는 동일한 도구로 개발 환경을 표준화할 수 없습니다.
4. Colima (Containers in Lima)
- 장점: GUI 없이 터미널 중심으로 작업하는 개발자에게 가장 가볍고 미니멀한 오픈소스(MIT) 솔루션입니다. Homebrew로 1분 만에 설치할 수 있습니다.
- 단점 및 한계:
- GUI 대시보드 부재: 모든 상태 확인과 관리를 오직 CLI 명령어로만 수행해야 하므로, 터미널 환경에 익숙하지 않은 주니어 개발자나 디자이너/기획자에게는 진입 장벽이 매우 높습니다.
- 파일 시스템 마운트 I/O 성능: macOS 호스트와 가상머신 간 대규모 소스코드(예: 방대한
node_modules폴더)를 볼륨 마운트할 때 VirtioFS 설정이 어긋나면 심각한 빌드 성능 저하나 파일 동기화 지연이 발생할 수 있습니다. - 트러블슈팅 난이도: 문제가 생겼을 때 백엔드인 Lima VM 내부로 직접 SSH 접속(
colima ssh)해 리눅스 레벨에서 디버깅해야 하는 경우가 많습니다.
로컬 컨테이너 도구 비교 및 트레이드오프
| 도구 | 라이선스 | GUI | 핵심 장점 | 현실적 단점 및 주의점 |
|---|---|---|---|---|
| Docker Desktop | 대기업 유료 (소기업/개인 무료) | O | 가장 뛰어난 호환성, Just works 편의성 | 무거운 리소스 점유, 대기업 유료 라이선스 비용 |
| Podman (Desktop) | 완전 오픈소스 (Apache 2.0) | O | 데몬리스/루트리스 보안성, 무료 대안 1순위 | docker.sock 연동 마찰, 볼륨 권한 및 컴포즈 호환성 엣지 케이스 |
| Rancher Desktop | 완전 오픈소스 (Apache 2.0) | O | containerd 지원, k3s 로컬 K8s 통합 제공 | 무거운 메모리/CPU 소모, 가상화 안정성 잔버그 |
| OrbStack | 상용 소프트웨어 (기업 유료) | O | 압도적인 속도와 극소의 배터리/메모리 소모 | macOS 전용, 기업 환경에서는 여전히 라이선스 구매 필요 |
| Colima | 완전 오픈소스 (MIT) | X | 터미널 중심의 초경량 미니멀 구성 | GUI 없음, 대용량 파일 마운트 I/O 이슈 가능성, 수동 트러블슈팅 |
결국 Docker Desktop의 유료화 이후 많은 엔지니어링 조직이 깨달은 교훈은 “소프트웨어 라이선스 비용을 아끼려다, 개발자들의 설정 시간과 트러블슈팅이라는 보이지 않는 인건비(Hidden Cost)가 더 크게 나갈 수도 있다” 는 현실이었습니다. 팀의 OS 구성, 보안 규정, 개발자들의 터미널 숙련도에 따라 신중한 트레이드오프가 필요한 이유입니다.
8. 정리: 런타임 계층을 이해한다는 것
컨테이너 기술은 10여 년에 걸쳐 “도커라는 거대한 만능 도구”에서 “관심사가 철저히 분리된 표준 모듈들의 결합”으로 성숙해졌습니다.
| 컴포넌트 | 역할 | 분류 | 표준 규격 |
|---|---|---|---|
| Docker | 빌드, 레지스트리, 로컬 실행 환경을 제공하는 통합 개발 플랫폼 | 도구/플랫폼 | - |
| containerd | 이미지 풀링, 라이프사이클, 스토리지 관리를 총괄하는 런타임 코어 | 고수준 런타임 | CRI 호환 |
| runc | cgroups/namespaces를 조작해 실제 프로세스를 띄우는 경량 실행기 | 저수준 런타임 | OCI 표준 |
이제 우리는 단일 서버 안에서 하나의 컨테이너가 어떤 원리로 띄워지고 관리되는지 그 바닥을 명확히 이해했습니다. 단일 호스트 수준에서 견고한 격리와 표준화된 런타임이 확립되었기에, 오늘날 우리는 수많은 컨테이너를 안정적으로 배포하고 운영할 수 있는 튼튼한 토대를 갖추게 되었습니다.