Docker가 MicroVM 내부에서 깨지는 이유 (Part 1): 당신이 몰랐던 Linux 가정

발행: (2026년 4월 24일 PM 02:36 GMT+9)
7 분 소요
원문: Dev.to

Source: Dev.to

초기 실패

마이크로VM 안에서 Docker를 실행하려고 했지만, 첫 번째 컨테이너가 시작되기도 전에 실패했습니다:

cgroup mountpoint does not exist

일반 EC2 인스턴스에서는 동일한 Docker 바이너리가 문제 없이 동작합니다. 문제는 Docker 자체나 커널 버그가 아니라, 마이크로VM에 존재하지 않는 Linux의 일부에 의존하고 있었기 때문입니다.

Cgroup 가정

Docker 오류에 cgroup이 언급되었으므로 파일 시스템을 살펴보았습니다:

ls /sys/fs/cgroup

출력 없음.

mount | grep cgroup

역시 아무것도 없음.

일반적인 Linux 시스템에서는 부팅 과정에서 무언가가 /sys/fs/cgroup을 자동으로 마운트하기 때문에 존재합니다. 마이크로VM 안에서는 그 단계가 전혀 이루어지지 않아 Docker가 cgroup 계층을 만들려고 했지만 커널이 “그런 인터페이스가 없다”고 응답했습니다.

계층을 수동으로 마운트했습니다:

mount -t cgroup2 none /sys/fs/cgroup

Docker가 조금 더 진행되었지만 또 다른 장벽에 부딪혔습니다. 이는 “Docker가 지금 존재한다고 가정하고 있는 것이 무엇인가?” 를 묻는 것이 중요함을 깨닫게 해 주었습니다. 단순히 “Docker가 왜 실패하는가?”를 찾는 것이 아니라 말이죠.

Systemd와 부팅 과정

systemd가 포함된 전체 Linux 배포판은 로그인하기 전에 많은 작업을 수행합니다:

  • /proc, /sys, /dev 마운트
  • cgroup 설정
  • 네트워킹 초기화
  • 런타임 환경 준비

마이크로VM은 이러한 작업을 자동으로 제공하지 않습니다—명시적으로 포함하지 않는 한 systemd가 없습니다. 따라서 /proc이나 /sys 마운트가 누락되거나 불완전해도 나중에 자동으로 고쳐지지 않으며, 부팅 과정을 직접 재현해야 합니다.

컨테이너 내부의 네트워킹 스택

기본 마운트를 해결한 뒤 Docker가 컨테이너 초기화를 시작했지만, 네트워킹이 깨졌습니다. 컨테이너가 인터넷에 어떻게 접근하는지를 이해하면 문제를 파악할 수 있습니다.

컨테이너 네트워크 네임스페이스

  • 각 컨테이너는 자체 IP를 가집니다(예: 172.17.x.x).
  • 호스트의 네트워크 인터페이스와 공유하지 않습니다.
  • 자체 네트워크 네임스페이스에서 실행됩니다.

Docker의 네트워크 설정

  1. Docker는 컨테이너용 새로운 네트워크 네임스페이스를 생성합니다.
  2. veth 쌍을 만듭니다: 한 쪽은 호스트에 남고, 다른 쪽은 컨테이너로 이동합니다.
  3. veth의 호스트 쪽은 docker0 브리지에 연결되어 컨테이너 간 통신을 가능하게 합니다.
  4. NAT가 적용되어 컨테이너를 떠나는 패킷의 출발 IP가 호스트 IP로 바뀌어 외부와 연결됩니다.

마이크로VM에서의 추가 레이어

우리 설정에서는 컨테이너가 마이크로VM 안에서 실행되었으며, 마이크로VM 자체가 호스트의 tap 디바이스에 연결된 가상 NIC을 가지고 있었습니다. 외부 트래픽의 전체 경로는 다음과 같습니다:

container → bridge (docker0) → VM eth0 → virtual NIC → host → internet

두 개의 겹친 네트워킹 환경이 존재하므로 어느 한 단계라도 누락되면 패킷이 목적지에 도달하지 못하고, 그 결과 오류는 종종 모호하게 나타납니다.

iptables와 패킷 필터링

Docker는 결국 다음과 같은 오류로 실패했습니다:

iptables: Failed to initialize nft: Protocol not supported

이 오류는 더 깊은 커널 기능에 뿌리를 두고 있습니다:

  • 커널에서 패킷 필터링이 구현되는 방식.
  • iptables가 그 구현과 상호 작용하는 방식.
  • 커널이 어떤 netfilter (nftables) 백엔드로 컴파일되었는지.

이를 해결하려면 이러한 하위 레벨 세부 사항을 이해해야 했습니다.

사고 모델 전환

가장 큰 변화는 기술적인 것이 아니라 개념적인 것이었습니다. 우리는 마이크로VM을 일반 머신처럼 다루는 것을 멈추고 새로운 접근 방식을 채택했습니다:

  • 존재한다고 가정하는 것이 전혀 없습니다.
  • 각 레이어를 모두 검증해야 합니다.
  • 각 수정이 다음 의존성을 드러냅니다.

즉, “Docker 디버깅”이 아니라 “작동하는 Linux 환경이 실제로 무엇으로 구성되어 있는가” 를 발견하는 과정이었습니다.

파트 2에서는 이 사고 모델이 특히 iptables 오류를 해결할 때 어떻게 도움이 되는지 살펴볼 예정입니다.

0 조회
Back to Blog

관련 글

더 보기 »