- Podman은 Docker와 비슷한 컨테이너 실행 경험을 제공하면서도 데몬 없이 동작해 보안과 감사 추적 측면에서 차별화됨
- Docker는 Docker daemon 중심의 클라이언트-서버 구조를 쓰지만, Podman은 사용자 세션에서 컨테이너를 직접 생성해 실행 사용자 추적이 더 명확함
- OCI 표준을 따르기 때문에 Docker Hub의
hello-world,caddy,wordpress,mysql:5.7같은 이미지를 실행할 수 있고, 많은 경우docker명령을podman으로 바꿔 사용할 수 있음 - 짧은 이미지 이름은 Docker처럼 자동으로 Docker Hub를 기본값으로 삼지 않으므로 완전한 이미지 이름, 별칭,
unqualified-search-registries설정 중 하나가 필요함 - 다중 컨테이너 구성은 Podman Compose, pods, Kubernetes 매니페스트로 처리할 수 있지만, Docker Swarm 같은 내장 프로덕션 오케스트레이션은 없어 Kubernetes 같은 외부 시스템을 써야 함
Podman과 Docker가 갈라지는 지점
- Podman은 Docker보다 더 안전하고 가벼운 대안을 목표로 하는 오픈소스 컨테이너 엔진임
- 지속적으로 떠 있는 데몬 없이 컨테이너를 실행하며, 사용자가 컨테이너를 직접 관리하는 구조를 가짐
- 기본 보안 방향은 rootless 컨테이너, 사용자 네임스페이스, 커널 capability의 더 신중한 사용에 맞춰져 있음
- Docker 이미지와 명령 체계와의 호환성이 높아 Docker 대안을 찾는 개발자와 시스템 관리자에게 실용적인 선택지가 됨
아키텍처와 감사 추적
- Docker는 클라이언트-서버 모델을 사용하며, 컨테이너 실행 요청은 Docker client에서 Docker daemon으로 전달됨
- 컨테이너 프로세스는 사용자 세션이 아니라 Docker daemon의 자식 프로세스가 됨
- Linux Audit 시스템인
auditd가 컨테이너 프로세스 이벤트를 감지할 때 audit user ID가 실제 사용자 ID가 아니라unset으로 표시될 수 있음 - 이 구조에서는 악성 활동을 특정 사용자와 연결하기 어려움
- Podman은 데몬리스 아키텍처를 사용함
- 각 컨테이너가 사용자 로그인 세션을 통해 직접 생성됨
- 컨테이너 프로세스 데이터가 사용자 정보를 유지함
auditd가 특정 컨테이너 프로세스를 시작한 사용자 ID를 정확히 감지하고 기록할 수 있음
- 이미지에 따라 Podman의 컨테이너 시작 속도는 Docker보다 최대 50% 빠를 수 있음
컨테이너 수명주기 관리
- Podman은 데몬이 없기 때문에 컨테이너 수명주기 관리 방식도 Docker와 다름
- Linux에서는 Systemd에 크게 의존함
--restart always플래그로 지정한 컨테이너의 재시작 정책을 적용하기 위해podman-restart라는systemd서비스를 사용함- 이 서비스는 시스템 재부팅 후 지정된 컨테이너를 자동으로 다시 시작함
- 실행 중인 컨테이너에서 Systemd 서비스 파일을 생성하는 명령도 제공함
- 컨테이너를
systemd관리 아래에 두면 시작, 중지, 점검이 쉬워짐
- 컨테이너를
- Docker는 이런 작업을 daemon 내부에서 처리함
오케스트레이션 선택지
- 로컬 개발에서 Docker 사용자는 보통 Docker Compose로 다중 컨테이너 애플리케이션을 정의하고 관리함
- Podman은 Compose 파일을 기본으로 지원하지 않지만, Podman Compose를 호환 대안으로 제공함
- 일반적으로 기존
docker-compose.yml파일과 함께 동작함 - Docker Compose에 익숙한 사용자는 기존 Compose 파일을 계속 사용할 수 있음
- 일반적으로 기존
- Podman의 네이티브 방식으로는 pods를 사용할 수 있음
- Kubernetes에서 가져온 개념임
- 여러 컨테이너를 하나의 단위처럼 관리할 수 있음
- 프로덕션 배포에서는 Podman에 Docker Swarm 같은 내장 오케스트레이션 도구가 없음
- 이 경우 Kubernetes 같은 외부 오케스트레이션 시스템이 대안이 됨
- Kubernetes는 Podman과 통합될 수 있지만, 올바르게 동작하려면 추가 구성과 설정이 필요할 수 있음
보안 기본값
- 컨테이너 보안에서 큰 위험은 컨테이너 탈출로 호스트 시스템이 침해되는 상황임
- Podman은 Docker보다 강한 기본 보안 설정을 제공하도록 설계됨
- rootless 컨테이너
- 사용자 네임스페이스
- seccomp 프로파일
- Docker에서도 rootless 컨테이너, 사용자 네임스페이스, seccomp 프로파일을 사용할 수 있지만 기본으로 활성화되어 있지 않고 추가 설정이 필요한 경우가 많음
- Podman 기본 구성은 격리된 사용자 네임스페이스 안에서 rootless 컨테이너를 실행해 잠재적 탈출의 영향을 제한함
- Docker 기본 설정은 컨테이너 프로세스를
root로 실행해 탈출 시 더 높은 위험을 가짐 - capability 기본값도 다름
- Podman은 기본적으로 11개 capability로 컨테이너를 시작함
- Docker는 더 허용적인 기본 설정으로 14개 capability를 사용함
- 두 도구 모두 강한 보안 구성으로 설정할 수 있지만, Podman은 일반적으로 그 상태에 도달하는 데 필요한 노력이 더 적음
기능 비교에서 눈에 띄는 차이
- Podman은 데몬리스 아키텍처와 Systemd 통합을 지원함
- 컨테이너를 pods로 묶을 수 있고 Kubernetes YAML도 다룰 수 있음
- Docker는 Docker Swarm을 지원하지만 Podman은 지원하지 않음
- 그 외 대부분의 기능은 양쪽이 대체로 동등하다고 볼 수 있음
설치와 실행 환경
- Podman은 Docker처럼 주요 운영체제에서 실행 가능함
- macOS
- Windows
- 주요 Linux 배포판
- 중요한 차이는 Linux에서는 네이티브로 실행되지만, Windows와 macOS에서는 가상 머신이 필요하다는 점임
- 예시는 Debian 기반 Linux 배포판인 Ubuntu, Mint, Debian을 가정함
- 최신 Podman을 설치하려면 비교적 최근 배포판이 필요함
- 글 작성 시점의 최신 주요 Podman 버전은
4.x - Ubuntu 22.04 LTS는 Podman
3.x에 묶여 있음 - 예시는 Ubuntu 23.10을 기준으로 함
- 글 작성 시점의 최신 주요 Podman 버전은
- 설치 후 예시 출력은
podman version 4.3.1이며, 로컬에서podman명령을 실행할 수 있음을 확인함
Docker 이미지 실행과 OCI 호환성
- Podman은 Docker 생태계 도구로 빌드된
hello-world이미지를 실행할 수 있음 - 이 호환성은 Docker와 Podman이 모두 OCI(Open Container Initiative) 표준을 따르기 때문임
- OCI는 이미지 형식 명세와 런타임 명세를 정의함
- 서로 다른 컨테이너 런타임이 상호 운용될 수 있게 함
- Docker Hub의 대부분 Docker 이미지와 컨테이너를 Podman에서 사용할 수 있음
- 기존 워크로드를 수정 없이 Podman으로 옮기거나 Docker Hub의 이미지 라이브러리를 활용할 수 있음
hello-world출력에 “Hello from Docker!”가 표시되더라도 실제 실행 주체는 Podman임- Docker client나 Docker daemon은 실행 과정에 관여하지 않음
짧은 이미지 이름 처리 방식
- Docker는 완전한 이미지 이름을 지정하지 않으면 Docker Hub인
docker.io를 기본 레지스트리로 사용함 - Podman은 짧은 이름 사용을 권장하지 않으며, 기본 레지스트리를 자동으로 가정하지 않음
hello-world는shortnames.conf에 별칭이 있어docker.io/library/hello-world로 해석됨caddy처럼 별칭이 없는 이미지를 짧은 이름으로 실행하면 다음 오류가 발생함Error: short-name "caddy" did not resolve to an alias and no unqualified-search registries are defined in "/etc/containers/registries.conf"
- 해결 방법은 세 가지임
- 완전한 이미지 이름을 사용해
docker.io/library/caddy처럼 명시함 registries.conf에[aliases]섹션을 추가해"caddy"="docker.io/caddy"로 별칭을 정의함unqualified-search-registries=["docker.io"]를 설정해 짧은 이름을 Docker Hub에서 찾도록 함
- 완전한 이미지 이름을 사용해
- 사용자별 설정은
$HOME/.config/containers/registries.conf에 둘 수 있음- 이 파일은
/etc/containers/registries.conf보다 우선함 - root 권한 없이 설정할 수 있어 rootless 접근 방식과 더 잘 맞음
- 이 파일은
- Docker 대체품처럼 Podman을 쓰려면 별칭보다
unqualified-search-registries설정이 장기적으로 편함
프라이빗 레지스트리 사용
- Podman은 Docker처럼 프라이빗 레지스트리를 사용할 수 있음
- Docker Hub 계정을 사용하는 예시는 다음 흐름을 따름
- Docker Hub에서 access token을 생성함
- 설명은
Podman tutorial, 권한은Read & Write로 설정함 - private repository를 생성함
podman login docker.io로 로그인함
docker.io가registries.conf의 첫 번째unqualified-search-registries항목이면 생략할 수 있지만, 레지스트리를 명시하는 것이 좋은 관행임- 레지스트리를 제공하지 않으면
podman login은 다음 오류로 실패함Error: no registries found in registries.conf, a registry must be provided
- 로그인 후
hello-world이미지를 private repository로 push하고, 로컬 public 이미지를 삭제한 뒤 private repository 이미지로 컨테이너를 실행할 수 있음 - 유효한 로그인 자격 증명이 없으면 private 이미지 pull 시 접근 거부와 인증 필요 오류가 발생함
- 프라이빗 레지스트리 사용에서 눈에 띄는 차이는
docker대신podman을 붙인다는 점이며, Podman은 널리 쓰이는 private registry와 함께 사용할 수 있음
Podman Compose로 다중 컨테이너 실행
- 여러 컨테이너를 하나의 단위로 실행해야 할 때 Podman은 여러 선택지를 제공함
- Podman Compose
- pods
- Kubernetes manifests
- 예시는 Podman Compose를 사용해 WordPress와 MySQL을 실행함
- Podman Compose는 커뮤니티 주도 도구이며 Compose specification을 구현하고 Podman과 통합됨
- Python 3에 의존하며, 예시에서는 pipx로 설치함
- 예시 설치 출력은
podman-compose 1.0.6 - 사용된 Podman 버전은
4.3.1
- 예시 설치 출력은
pipx가$HOME/.local/bin에 설치되면 해당 경로가$PATH에 없을 수 있음pipx ensurepath로 경로를 추가할 수 있음- 새 터미널을 열거나 셸 설정 파일을 다시 읽어야 함
WordPress와 MySQL 예시
- 예시는
.env파일에 데이터베이스 사용자, 비밀번호, 이름을 정의하고docker-compose.yml로 WordPress와 MySQL 서비스를 구성함 podman-compose up -d실행 시 Podman Compose는docker-compose.yml을 분석함wordpress서비스 처리 과정- 필요한 external volume을 찾고 없으면 생성함
- 적절한 network를 찾고 없으면 생성함
wordpress컨테이너를 실행함- 로컬 이미지가 없으면 설정된
docker.io레지스트리에서wordpress:latest를 가져옴
db서비스 처리 과정podman-tutorial_dbvolume을 생성함- 기존 네트워크를 확인함
mysql:5.7컨테이너를 실행함- 로컬 이미지가 없으면 Docker Hub에서 가져옴
- 실행 후
localhost:8080에서 WordPress 설치 페이지를 확인할 수 있음 podman ps출력에는wordpress와db컨테이너가 실행 중으로 표시됨wordpress는0.0.0.0:8080->80/tcp로 포트가 매핑됨db는mysql:5.7이미지로 실행됨
- 이미지 목록에는
docker.io/library/wordpress:latest와docker.io/library/mysql:5.7이 표시됨 - 네트워크 목록에는 기본
podman네트워크와 Podman Compose가 만든podman-tutorial_default네트워크가 표시됨podman-tutorial_default는docker-compose.yml에 정의된 컨테이너를 같은 시스템의 다른 컨테이너와 분리하기 위해 생성됨
- volume 목록에는
podman-tutorial_db와podman-tutorial_wordpress가 표시됨 podman-compose down은 컨테이너를 중지하고 제거하지만 네트워크와 volume은 유지함- volume 제거에는
podman volume rm을 사용함 - 네트워크 제거에는
podman network rm을 사용함
- volume 제거에는
- 명령은 Docker 및 Docker Compose와 거의 같고,
docker와docker-compose대신podman과podman-compose를 입력하는 차이가 있음
선택 기준
- Podman은 컨테이너 워크로드 실행을 위한 Docker의 실용적인 대안임
- Docker가 할 수 있는 대부분의 작업을 수행할 수 있고, 백그라운드 데몬이 필요 없다는 장점이 있음
- Docker에는 없는 기능도 제공함
- Kubernetes manifest 파일 작업
- 개별 컨테이너를 pods로 구성
- 더 가볍고 안전한 컨테이너 관리 솔루션이 필요하면 Podman이 더 나은 선택일 수 있음
- 강력한 생태계와 광범위한 커뮤니티 지원을 우선하면 Docker가 더 적합할 수 있음
- 추가 탐색 자료로 Podman 공식 웹사이트, 문서, 커뮤니티를 참고할 수 있음