LabHub
배우기 러닝패스 코스

Running Rootless Podman

Operating Rootless Containers

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

rootless 로 컨테이너를 실행하고, 볼륨·사용자 매핑·포트 제약을 직접 확인하고, Quadlet 유닛 파일을 작성합니다.

왜 중요한가

docker 에서 podman 으로 옮길 때 반드시 걸리는 것이 정해져 있습니다. restart: always 가 부팅 자동 시작을 뜻하지 않고(데몬이 없으니까), 1024 미만 포트에 바인딩할 수 없고, 볼륨 파일의 소유자가 낯선 UID 로 보이고, SELinux 환경에서는 :Z 라벨이 없으면 Permission denied 가 납니다. 이 네 가지를 미리 알면 전환이 30분이고 모르면 반나절입니다.

그리고 부팅 자동 시작의 podman 식 정답은 Quadlet 입니다. .container 파일을 두면 systemd 가 그것을 읽어 서비스 유닛을 생성합니다. podman generate systemd 는 구식이 됐습니다.\n\n## 이 실습은 가상머신에서 돕니다\n\nrootless podman 이 진짜로 돕니다. 파드에서는 newuidmapCAP_SETUID 를 요구해서 subuid 대역을 줄 수 없었고, 그래서 이 실습이 반쪽이었습니다 — 컨테이너가 실제로 뜨지 않으니 채점도 파일만 볼 수밖에 없었습니다.\n\nVM 에서는 podman run 이 그대로 되고, 7단계의 Quadlet 도 정말 서비스로 번역되어 뜹니다. systemctl --user status labhub-web 로 직접 확인할 수 있습니다. 처음 뜨는 데 1분 남짓 걸립니다.

단계

  1. /root/podrun 디렉터리를 만들고, podster 권한으로 /opt/images/labhub-alpine.tar 를 적재한 뒤 이미지 목록을 /root/podrun/images.txt 로 저장하세요.
  2. 그 이미지로 컨테이너를 한 번 실행해 echo labhub-ok 를 수행하고, 출력을 /root/podrun/run.txt 로 저장하세요.
  3. /home/podster/data 를 컨테이너의 /data 로 마운트해 컨테이너 안에서 /data/hello.txt 를 만들고, 호스트에서 그 파일이 보이는지 확인해 /root/podrun/volume.txt 에 파일 경로와 내용을 저장하세요.
  4. 3번에서 만든 파일의 호스트 쪽 소유자 UID 를 숫자 한 줄로 /root/podrun/owner.txt 에 적으세요.
  5. 특권 포트 게시를 시도해 실패시키고, 그 오류 메시지를 /root/podrun/port-fail.txt 로 저장하세요. 그다음 8090 포트로 다시 시도해 성공한 결과를 /root/podrun/port-ok.txt 로 저장하세요.
  6. labhub-web 이라는 이름으로 컨테이너를 백그라운드 실행하고, podman ps 출력을 /root/podrun/ps.txt 로 저장하세요. 목록에 그 이름이 보여야 합니다.
  7. /home/podster/.config/containers/systemd/labhub-web.container 를 작성하세요. [Unit], [Container], [Install] 세 섹션이 있어야 하고, [Container] 에는 Image, PublishPort, Volume 세 키가, [Install] 에는 WantedBy 가 있어야 합니다.
  8. /root/podrun/diff.txt 를 다음 6줄로 만드세요. DAEMON=none / STORAGE=<podster 의 graphRoot 절대 경로> / PRIVPORT=denied / RESTART=quadlet / GPUFLAG=--device / SELINUX_LABEL=:Z

참고

이미지 적재

/root/podrun 디렉터리를 만들고, podster 권한으로 /opt/images/labhub-alpine.tar 를 적재한 뒤 이미지 목록을 /root/podrun/images.txt 로 저장하세요.

인터넷이 없으므로 미리 준비된 아카이브를 씁니다. 적재 후 목록에서 확인하세요.

컨테이너 실행

그 이미지로 컨테이너를 한 번 실행해 echo labhub-ok 를 수행하고, 출력을 /root/podrun/run.txt 로 저장하세요.

일회성 실행에는 종료 후 정리하는 옵션을 붙입니다. 출력을 파일로 남기세요.

볼륨 마운트

/home/podster/data 를 컨테이너의 /data 로 마운트해 컨테이너 안에서 /data/hello.txt 를 만들고, 호스트에서 그 파일이 보이는지 확인해 /root/podrun/volume.txt 에 파일 경로와 내용을 저장하세요.

호스트 경로와 컨테이너 경로를 콜론으로 잇습니다. SELinux 환경을 대비해 라벨 옵션도 붙이세요.

사용자 매핑 확인

3번에서 만든 파일의 호스트 쪽 소유자 UID 를 숫자 한 줄로 /root/podrun/owner.txt 에 적으세요.

볼륨에 만든 파일을 호스트에서 보면 소유자가 매핑된 UID 로 보입니다. keep-id 옵션을 쓰면 달라집니다.

특권 포트 실패 재현

특권 포트 게시를 시도해 실패시키고, 그 오류 메시지를 /root/podrun/port-fail.txt 로 저장하세요. 그다음 8090 포트로 다시 시도해 성공한 결과를 /root/podrun/port-ok.txt 로 저장하세요.

1024 미만 포트를 게시하려 하면 실패합니다. 그 오류 메시지를 그대로 저장하고 높은 포트로 다시 시도하세요.

실행 중 컨테이너 확인

labhub-web 이라는 이름으로 컨테이너를 백그라운드 실행하고, podman ps 출력을 /root/podrun/ps.txt 로 저장하세요. 목록에 그 이름이 보여야 합니다.

이름을 지정해 띄우면 관리가 쉽습니다. 출력 형식을 지정하는 옵션이 있습니다.

Quadlet 유닛 작성

/home/podster/.config/containers/systemd/labhub-web.container 를 작성하세요. [Unit], [Container], [Install] 세 섹션이 있어야 하고, [Container] 에는 Image, PublishPort, Volume 세 키가, [Install] 에는 WantedBy 가 있어야 합니다.

확장자가 .container 인 파일입니다. [Container] 섹션에 Image 가 필수이고 [Install] 도 필요합니다.

docker 와의 차이 정리

/root/podrun/diff.txt 를 다음 6줄로 만드세요. DAEMON=none / STORAGE=<podster 의 graphRoot 절대 경로> / PRIVPORT=denied / RESTART=quadlet / GPUFLAG=--device / SELINUX_LABEL=:Z

값은 앞 단계에서 실제로 확인한 것이어야 합니다. 저장 경로는 절대 경로로 적으세요.