LabHub

블로그

Docker에서 Podman으로 — 데몬 없는 컨테이너 엔진 전환 완전 가이드

한국어English日本語中文

들어가며 — 명령어는 같은데 철학이 다르다

Podman의 첫인상은 "docker를 podman으로 바꿔 치면 되는 도구"입니다. 실제로 alias docker=podman으로 대부분의 명령이 그대로 동작하고, 공식적으로도 Docker CLI 호환을 목표로 합니다. 하지만 그 표면 아래의 아키텍처는 정반대에 가깝습니다 — 그리고 전환에서 마주치는 모든 차이(설정 파일 위치, GPU 설정, compose, 권한 문제)는 이 아키텍처 차이에서 흘러나옵니다.

이 글은 그 차이를 뿌리부터 정리합니다. 참고로 이 글의 명령어는 Podman 5.x / Docker Engine 27+ 기준입니다.

내부 동작 — 데몬 vs fork-exec

Docker의 구조는 클라이언트-서버입니다. docker run을 치면 CLI는 REST 요청을 만들어 dockerd 데몬에 보내고, 데몬이 containerd에, containerd가 runc에 위임해 컨테이너를 만듭니다. 모든 컨테이너의 부모는 결국 데몬입니다.

Docker:  docker CLI ──REST──▶ dockerd ──▶ containerd ──▶ runc ──▶ 컨테이너
Podman:  podman CLI ──fork/exec──▶ conmon ──▶ crun(runc) ──▶ 컨테이너

Podman에는 데몬이 없습니다. podman run은 평범한 프로세스처럼 fork-exec으로 컨테이너를 직접 만듭니다. 컨테이너마다 작은 감시 프로세스인 conmon이 붙어 stdio와 exit code를 관리하고, 실제 생성은 OCI 런타임 crun(C로 작성, runc보다 가볍고 빠름)이 수행합니다. 이 구조의 함의:

Rootless — 기본값의 차이

두 엔진 모두 rootless 모드를 지원하지만 무게중심이 다릅니다. Docker는 rootful이 기본이고 rootless가 옵트인, Podman은 rootless가 기본 경험입니다(Fedora/RHEL에서는 설치 직후 일반 사용자로 바로 씁니다).

rootless의 원리는 user namespace입니다. 컨테이너 안의 root(UID 0)는 밖에서는 내 계정의 UID로, 컨테이너 안의 다른 UID들은 /etc/subuid·/etc/subgid에 할당된 보조 UID 대역으로 매핑됩니다. 컨테이너가 탈옥해도 손에 쥐는 것은 일반 사용자 권한뿐입니다.

전환 시 알아야 할 rootless의 제약:

설정 파일 — 어디에 무엇이 있나

Docker의 설정이 데몬 중심(daemon.json)이라면, Podman은 라이브러리 중심의 분산 설정입니다. 시스템 전역은 /etc/containers/, 사용자별은 ~/.config/containers/가 우선합니다.

Docker                              Podman
──────────────────────────────      ─────────────────────────────────────────
/etc/docker/daemon.json             /etc/containers/containers.conf   (엔진·런타임 옵션)
                                    ~/.config/containers/containers.conf
(레지스트리 미러 등도 daemon.json)   /etc/containers/registries.conf   (레지스트리·미러·차단)
                                    /etc/containers/storage.conf      (스토리지 드라이버·경로)
                                    /etc/containers/policy.json       (이미지 서명 정책)
~/.docker/config.json (인증)        ~/.config/containers/auth.json    (레지스트리 인증)

이미지·컨테이너 저장 위치
/var/lib/docker                     rootful:  /var/lib/containers/storage
                                    rootless: ~/.local/share/containers/storage

전환 시 가장 자주 손대는 것 두 가지: registries.confunqualified 이미지 검색 레지스트리를 지정하는 것(Docker는 nginx를 자동으로 docker.io로 해석하지만 Podman은 기본적으로 어느 레지스트리인지 묻거나 설정을 따릅니다 — unqualified-search-registries = ["docker.io"]를 넣으면 Docker와 동일해집니다), 그리고 사내 미러/인증을 registries.conf + auth.json으로 옮기는 것입니다.

GPU — CDI가 정답이다

NVIDIA GPU를 Podman에서 쓰는 표준 경로는 CDI(Container Device Interface) 입니다. CDI는 "이 장치를 컨테이너에 넣으려면 어떤 디바이스 노드·라이브러리·환경변수가 필요한가"를 기술하는 벤더 중립 스펙으로, Docker의 --gpus 같은 런타임 훅 방식보다 투명하고 이식성이 높습니다(쿠버네티스의 GPU Operator도 내부적으로 CDI를 씁니다).

# 1) nvidia-container-toolkit 설치 후 CDI 스펙 생성
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml

# 2) 생성된 장치 이름 확인
nvidia-ctk cdi list
#   nvidia.com/gpu=0, nvidia.com/gpu=all, (MIG면) nvidia.com/gpu=0:0 ...

# 3) 컨테이너에서 GPU 사용
podman run --rm --device nvidia.com/gpu=all \
  nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi

Compose — compose.yaml을 그대로 쓸 수 있는가?

결론부터: 대부분 그대로 쓸 수 있고, 방법이 두 가지입니다.

방법 1 — Docker Compose 바이너리를 Podman 소켓에 연결(권장). Podman은 Docker API 호환 소켓을 제공할 수 있습니다. 이 소켓을 켜면 표준 docker compose가 백엔드만 Podman인 채로 그대로 동작합니다 — compose.yaml 재작성이 필요 없습니다.

# 사용자 소켓 활성화 (rootless)
systemctl --user enable --now podman.socket

# docker compose가 Podman 소켓을 보도록 지정
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock

docker compose up -d   # 백엔드는 Podman

Go로 구현된 정식 Compose 스펙 구현체를 그대로 쓰므로 호환성이 가장 높습니다. podman compose 명령 자체도 외부 컴포즈 프로바이더(설치되어 있으면 docker-compose)를 호출하는 래퍼입니다.

방법 2 — podman-compose. 파이썬으로 재구현된 별도 프로젝트입니다. 데몬/소켓 없이 podman 명령을 직접 호출하는 순수 구현이라는 장점이 있지만, Compose 스펙의 구석(일부 네트워크 옵션, profiles, 고급 depends_on 조건 등)에서 정식 구현과 미묘한 차이가 날 수 있습니다. 간단한 스택에는 충분하고, 복잡한 compose 파일이라면 방법 1이 안전합니다.

전환 시 compose 관련 주의점:

전환 함정 모음 — 미리 알면 30분, 모르면 반나절

버전과 커뮤니티 — 누가 만들고 어디서 논의되나

버전 감각(2026년 기준): Podman은 5.x 세대로, 4.x에서 5.0으로 넘어오며 네트워킹 기본값이 pasta로 바뀌고 CDI 지원이 성숙했습니다. RHEL 9/10에 깊이 통합되어 있고 Fedora는 여러 릴리스째 Podman이 기본 컨테이너 도구입니다. Docker Engine은 27+ 세대이며 여전히 가장 큰 생태계와 문서량을 가집니다.

거버넌스와 커뮤니티:

어느 쪽을 쓸까의 실용적 기준: 팀이 RHEL/Fedora 계열이거나, rootless 보안이 요구사항이거나, systemd 기반 운영을 선호한다면 Podman이 자연스럽습니다. Docker Desktop 의존 도구가 많거나 생태계 문서량이 중요하다면 Docker가 여전히 무난합니다. 그리고 둘은 같은 OCI 표준 위에 있으므로, 이미지는 어느 쪽에서 빌드해도 어느 쪽에서든 돌아갑니다 — 표준이 있다는 것의 축복입니다.

마치며

Docker에서 Podman으로의 전환은 명령어 교체가 아니라 운영 모델의 교체입니다 — 데몬에서 fork-exec으로, rootful에서 rootless로, daemon.json에서 containers.conf 가족으로, --gpus에서 CDI로, compose 데몬 의존에서 소켓 호환 또는 systemd/Quadlet으로. 다행히 OCI 표준 덕에 이미지와 compose.yaml 같은 산출물은 거의 그대로 넘어가고, 함정은 위에 정리한 몇 가지(SELinux 라벨, unqualified 이미지, 저장 경로)로 수렴합니다. 컨테이너 기초를 손으로 다지고 싶다면 이 사이트의 컨테이너 실습실리눅스 터미널도 활용해 보세요.

참고 자료

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다