Tech_News

Apple container의 Container Machine: Docker Desktop 없이 맥에서 진짜 리눅스 환경 굴리기

TeEm0 2026. 6. 11. 09:00

맥북을 개발 머신으로 쓰는 백엔드/인프라 엔지니어라면 한 번쯤 고민해봤을 거다. "Docker Desktop 라이선스도 신경 쓰이고, 리소스도 많이 먹고… 대안이 뭐가 있나." Lima, Colima, OrbStack로 갈아탄 사람도 많을 거다. 그런데 작년부터 Apple이 직접 apple/container 프로젝트를 GitHub에 올리면서 판이 좀 달라졌다. 이번 글에서는 그중에서도 최근 Hacker News에서 화제가 된 Container Machine 문서를 실무자 시선으로 뜯어본다.

먼저 분명히 해두자. 이 글은 공식 문서(container-machine.md)를 기준으로 쓴다. 문서에 없는 벤치마크 수치나 버전별 동작은 함부로 단정하지 않고, 확인이 필요한 부분은 그렇게 표시한다.

1. 왜 지금 화제이고 어떤 문제를 푸는가

우리가 흔히 쓰는 컨테이너는 "애플리케이션 하나"를 모델로 한다. nginx 이미지, postgres 이미지처럼 프로세스 하나 띄우고 끝나는 구조다. 그런데 실무에서 의외로 자주 필요한 건 그게 아니다. "리눅스 환경 자체"가 필요할 때가 있다.

  • 로컬은 맥인데, 빌드와 실행은 리눅스에서 검증하고 싶을 때
  • systemd 기반으로 돌아가는 서비스(예: postgresql, redis를 시스템 서비스로)를 통째로 테스트하고 싶을 때
  • alpine, ubuntu, debian 등 타겟 배포판별로 동작을 확인해야 할 때

Container Machine은 바로 이 지점을 노린다. 공식 문서의 표현을 빌리면 "A container machine is modeled after a Linux environment". 즉 앱 하나가 아니라 init 시스템까지 포함한 리눅스 환경 전체를 가볍고 영구적인(persistent) 형태로 맥 위에서 돌리는 게 목표다.

Docker Desktop이나 Lima와의 가장 큰 차이는 호스트 통합이다. 문서가 강조하는 핵심 컨셉이 "Edit on the Mac, build inside"인데, 풀어보면 이렇다.

  • 내 맥 홈 디렉토리($HOME)에 있는 레포가 컨테이너 머신 안에서도 그대로 보인다.
  • 맥 계정 username과 home 디렉토리가 자동으로 리눅스 환경에 매핑된다. whoami를 쳐도 root가 아니라 내 호스트 계정 이름이 나온다.
  • 맥에서 VS Code로 코드를 짜고, 빌드/실행은 리눅스 안에서, 그리고 결과물은 다시 맥 네이티브 도구(브라우저, 프로파일러 등)로 들여다본다. 복사 단계가 없다.

OrbStack을 써본 사람이라면 "어? 그거 OrbStack도 비슷하게 해주는데?"라고 할 거다. 맞다. 컨셉은 OrbStack의 머신 기능과 상당히 겹친다. 차이라면 이건 Apple이 직접 관리하는 오픈소스이고, 애초에 Apple Silicon + Virtualization.framework 위에서 돌도록 설계됐다는 점이다.

2. 동작 원리: 명령어로 직접 보기

백문이 불여일견. Quickstart부터 따라가 보자. 문서 기준 가장 기본 흐름이다.

# alpine 기반 컨테이너 머신을 'dev'라는 이름으로 생성
container machine create alpine:latest --name dev

# 컨테이너 머신 안에서 whoami 실행
container machine run -n dev whoami

여기서 핵심은 출력이다. 일반 컨테이너에서 whoami를 치면 보통 root가 나오는데, 컨테이너 머신은 다르다.

$ container machine run -n dev whoami
your-mac-username      # root가 아니라 호스트 맥 계정 이름

$ container machine run -n dev pwd
/home/your-mac-username   # 맥 홈 디렉토리가 마운트된 위치

이게 바로 "username과 home 디렉토리 자동 매핑"이 동작하는 모습이다. 인자 없이 container machine run -n dev만 치면 인터랙티브 셸로 들어가고, 이 안에서 내 레포 디렉토리로 cd하면 맥에서 작업하던 파일이 그대로 보인다.

명령 단위로 한 번만 실행하고 빠지고 싶으면 이렇게 쓴다. -- 뒤에 붙이는 형태도 지원한다.

$ container machine run -n dev uname -a
Linux dev 6.x.x ... aarch64 GNU/Linux

$ container machine run -n dev -- cat /proc/cpuinfo

매번 -n dev를 붙이기 귀찮으면 기본 머신을 지정해두면 된다. 그리고 container machinem이라는 짧은 별칭이 있어서 m ls, m run처럼 쓸 수 있다.

container machine set-default dev
container machine run        # 이제 -n 없이도 dev에서 동작

# 별칭 사용
m ls          # 모든 컨테이너 머신 목록
m inspect dev # dev의 JSON 상세 정보
m stop dev    # 중지
m rm dev      # 영구 스토리지까지 포함해 삭제

격리 모델은 어떻게 되나

여기서부터는 문서에 명시된 범위와 합리적 추론을 구분해서 말하겠다. Apple의 container 프로젝트는 일반적으로 각 컨테이너를 경량 VM 위에서 격리하는 구조로 알려져 있고, 이는 Virtualization.framework를 기반으로 한다. 컨테이너 머신 역시 init 시스템(/sbin/init)을 직접 부팅한다는 점에서 단순 namespace 격리가 아니라 VM 경계를 가진 풀 리눅스 환경에 가깝다.

다만 "컨테이너마다 별도 VM인지, 머신마다 하나의 VM인지"의 구체적인 구현 디테일은 이 container-machine.md 문서만으로는 단정하기 어렵다. 실제 격리 단위와 커널 공유 여부는 프로젝트 상위 문서 확인이 필요하다. 다만 실무 체감상 중요한 건, init/systemd를 띄울 수 있다는 사실 자체다. 문서에도 이렇게 적혀 있다.

Run a database or whatever your stack needs as a system service — systemctl start postgresql works on images with systemd installed.

일반 컨테이너에서 systemd 띄우려고 --privileged에 cgroup 마운트 삽질해본 사람이라면, 이게 기본으로 된다는 게 얼마나 편한지 알 거다.

3. 실무 관점: 고려사항, 트레이드오프, 흔한 함정

리소스 설정 — 메모리 기본값이 호스트의 절반이다

이거 모르고 쓰면 맥 전체가 버벅인다. 문서에 명시되어 있다. "Memory defaults to half of host memory." 16GB 맥북이면 컨테이너 머신 하나가 기본 8GB를 잡아간다는 얘기다. 여러 머신을 동시에 띄우는 시나리오라면 반드시 조정하자.

# CPU 4개, 메모리 8G로 변경
container machine set -n dev cpus=4 memory=8G

# 설정은 재시작 후 적용된다 — 이 순서가 중요
container machine stop dev
container machine run -n dev -- nproc

흔한 함정 하나: set으로 바꿔놓고 바로 적용 안 됐다고 당황하는 경우. 문서가 분명히 못 박는다. "Changes take effect after the next stop and start." 즉 실행 중인 머신에 즉시 반영되지 않는다. stoprun(또는 start)을 거쳐야 한다. CI 스크립트에서 동적으로 리소스 바꾸려다 이걸로 한참 헤매기 좋다.

볼륨/홈 마운트 모드 — ro로 묶다가 빌드가 깨진다

홈 마운트는 세 가지 모드가 있다. rw(기본), ro, none. 보안이나 실수 방지 목적으로 ro로 걸어두는 건 좋은데, 빌드 산출물을 홈 디렉토리 하위에 쓰는 툴체인을 쓰면 권한 에러로 빌드가 깨진다. 리눅스 안에서 흔히 이런 메시지를 보게 된다.

Read-only file system
error: failed to write to /home/your-username/project/target/...:
Read-only file system (os error 30)

이건 마운트 모드가 ro일 때 전형적으로 만나는 패턴이다. 빌드 캐시나 산출물 디렉토리를 홈 밖(예: 머신 내부 임시 경로)으로 빼거나, 마운트를 rw로 두는 식으로 우회해야 한다.

BYO 이미지 — systemd 없으면 그냥 컨테이너다

문서가 명확히 한 조건이 있다. "Any Linux image that includes /sbin/init works as a container machine." 즉 init이 없는 minimal 이미지를 그대로 쓰면 컨테이너 머신의 장점(서비스 supervisor, systemctl)을 못 쓴다. systemd 깔린 Ubuntu 머신을 직접 빌드하려면 문서의 Dockerfile을 거의 그대로 따라가야 한다.

FROM ubuntu:24.04
ENV container container
RUN apt-get update \
    && apt-get install -y \
       dbus systemd openssh-server net-tools iproute2 \
       iputils-ping curl wget vim-tiny man sudo \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && yes | unminimize
RUN systemctl set-default multi-user.target
# (이하 hugepages.mount 등 불필요 유닛 mask/disable 생략)
# 이미지 빌드 후 머신으로 생성
container build -t local/ubuntu-machine:latest .
container machine create local/ubuntu-machine:latest --name ubuntu

여기서 알아둘 디테일 하나. 첫 부팅 시 Apple이 기본 setup 스크립트를 돌려서 호스트 계정 매핑 유저를 만든다. 이걸 직접 제어하고 싶으면 이미지에 /etc/machine/create-user.sh 실행 스크립트를 넣으면 된다. root로, 첫 부팅에 한 번만 실행되며 CONTAINER_UID, CONTAINER_GID, CONTAINER_HOME, CONTAINER_USER, CONTAINER_MACHINE_ID 환경변수가 주어진다. 사내 표준 유저 설정(특정 그룹, sudoers 등)을 강제해야 하는 팀이라면 이 훅이 꽤 유용하다.

네트워킹 — 문서 범위 밖이라 단정 금지

개요에서 "네트워킹 구조 분석"을 기대했을 텐데, 솔직하게 말하면 container-machine.md 문서 자체에는 컨테이너 간 통신이나 호스트 브리지 동작에 대한 구체적 서술이 없다. 빌드한 Ubuntu 이미지에 net-tools, iproute2, iputils-ping을 넣는 걸로 보아 네트워크 도구가 동작하는 환경인 건 분명하지만, 구체적인 브리지/포트포워딩 동작 원리는 별도 네트워킹 문서로 확인이 필요하다. 여기서 추측으로 채우면 그게 바로 검색 유입자에게 잘못된 정보를 주는 길이라, 확인 전엔 단정하지 않겠다.

성능 비교 — 실측 수치는 직접 재라

마찬가지로 Docker Desktop / Lima / OrbStack 대비 정량 벤치마크는 이 문서에 없다. 다만 설계상 추론할 수 있는 트레이드오프는 있다.

  • 장점 방향: Apple Silicon + Virtualization.framework 네이티브 설계라 ARM 리눅스 환경에서의 오버헤드가 작을 것으로 기대된다. 홈 디렉토리 직접 마운트라 파일 동기화 복사 비용이 없다.
  • 비용 방향: 머신마다 init/systemd 풀 부팅 + 기본 메모리 절반 할당이라, "앱 컨테이너 하나만 가볍게"라는 용도엔 과하다.

실제 도입 검토라면 본인 워크로드(예: cargo build, go build, DB 부하 테스트)로 Docker Desktop/OrbStack과 직접 시간을 재서 비교하는 걸 권한다. 일반론으로 "더 빠르다"고 말하는 게 가장 위험하다.

4. 정리: 한 줄 요약과 도입 판단

한 줄 요약: Container Machine은 "앱 컨테이너"가 아니라 "내 맥 홈이 그대로 들어간 영구 리눅스 환경"을 Apple Silicon 위에서 네이티브로 굴리는 도구다.

이런 사람한테 맞다:

  • 맥에서 코드 짜고 리눅스에서 빌드/테스트하는 워크플로우가 일상인 백엔드/시스템 개발자
  • systemd 기반 서비스(DB 포함)를 로컬에서 통째로 띄워 검증해야 하는 경우
  • alpine/ubuntu/debian 멀티 배포판 호환성을 자주 확인하는 라이브러리/CLI 메인테이너
  • Docker Desktop 라이선스/리소스 부담에서 벗어날 오픈소스 대안을 찾는 팀

아직 신중해야 할 경우:

  • 프로덕션 CI의 핵심 빌드 인프라로 바로 올리기엔, 네트워킹·성능 특성이 공개 문서로 충분히 검증되지 않았다. 로컬 개발 보조부터 시작하는 게 안전하다.
  • Intel 맥 사용자. 이 프로젝트는 Apple Silicon 전제다.
  • "앱 하나만 가볍게" 돌리는 용도라면 풀 init 부팅과 메모리 절반 기본값이 오히려 부담이다 — 이 경우는 기존 컨테이너 런타임이 낫다.

개인적으론 OrbStack 머신 기능을 잘 쓰던 사람이라면 컨셉 이해가 빠를 거고, "Apple 공식 + 오픈소스"라는 점에서 장기적으로 지켜볼 가치가 충분하다고 본다. 다만 지금 시점에선 메인 개발 환경을 통째로 갈아엎기보다, 별도 머신 하나 만들어서 멀티 배포판 테스트나 systemd 서비스 검증 용도로 먼저 굴려보길 권한다.

참고 자료

728x90