Docker menempatkan seluruh mesin container pada satu proses: daemon dockerd yang berjalan sebagai root dan menerima perintah lewat socket. Arsitektur itu praktis, tetapi konsekuensinya besar — daemon mati berarti semua container kehilangan pengelolanya, dan siapa pun yang bisa bicara ke socket-nya memegang kekuasaan root di host. Podman membuang perantara itu sepenuhnya: perintah podman menjalankan container langsung sebagai proses anak, dan berjalan tanpa root sejak awal. Chapter ini membedah arsitektur daemonless, keunggulan rootless, konsep pod, dan ekosistem di sekitarnya — dan karena podman tidak terpasang di lingkungan latihan, pembuktiannya lewat fixture dan simulasi yang bisa diverifikasi.
Arsitektur Tanpa Daemon #
Dalam Docker, docker run sebenarnya tidak menjalankan container: perintah itu mengirim permintaan ke dockerd lewat /var/run/docker.sock, dan daemon-lah yang mem-fork container. Podman membuang perantara: podman run mem-fork container sebagai proses anaknya sendiri, dikawal proses kecil bernama conmon yang mencatat log dan melaporkan exit code. Konsekuensinya bertingkat:
| Aspek | Docker | Podman |
|---|---|---|
| Arsitektur | client–server lewat daemon dockerd | langsung fork–exec dari CLI |
| Daemon | satu proses untuk semua container | tidak ada; tiap container mandiri |
| Daemon mati | container kehilangan pengelola | tidak ada yang berubah |
| Pemegang kuasa | root (atau anggota grup docker) | user yang menjalankan perintah |
| Auto-restart | fitur daemon --restart | diserahkan ke systemd |
Baris terakhir bukan kelemahan melainkan pilihan sadar: alat yang tepat untuk proses yang harus selalu hidup adalah service manager, dan integrasinya kita praktikkan pada bagian penutup chapter.
Komando Kompatibel #
Podman sengaja memelihara kompatibilitas dengan CLI Docker — banyak skrip lama cukup mengganti kata pertamanya:
| Docker | Podman |
|---|---|
docker run -d --name web nginx | podman run -d --name web nginx |
docker ps -a | podman ps -a |
docker build -t app . | podman build -t app . |
docker exec -it web sh | podman exec -it web sh |
Bahkan alias docker=podman di ~/.bashrc sudah cukup untuk sebagian besar kasus. Nama berkas resepnya pun dibakukan ulang menjadi Containerfile — isinya sama persis dengan Dockerfile, dan podman membaca kedua nama itu. Berikut contoh tampilan podman ps pada mesin dengan dua container rootless:
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
3f9c2a1b8e74 docker.io/library/nginx:1.27 nginx -g daemon o... Up 2 minutes 0.0.0.0:8080->80/tcp web-toko
8d4e6f0a2c19 docker.io/library/postgres:17 postgres Up 2 minutes db-tokoRootless dan User Namespace #
Keunggulan keamanan terbesar podman ada pada satu kata: rootless — container berjalan tanpa user root di host. Mekanismenya adalah user namespace: kernel memetakan ulang UID. User budi di host memetakan dirinya sebagai UID 0 di dalam container (di sanalah asal root di dalam container), sementara 65.535 UID berikutnya diambil dari rentang bawahan yang terdaftar di /etc/subuid. Berikut isi tipikal berkas itu:
# format subuid: nama:start:jumlah
printf 'budi:100000:65536\nsiti:265536:65536\n' > subuid
cat subuid
awk -F: '{printf "%s: UID %d s/d %d (%d UID bawahan)\n", $1, $2, $2+$3-1, $3}' subuidOutput yang Dihasilkan:
budi:100000:65536
siti:265536:65536
budi: UID 100000 s/d 165535 (65536 UID bawahan)
siti: UID 265536 s/d 331071 (65536 UID bawahan)Mari kita bedah bloknya:
printf ... > subuid: fixture dua baris — setiap user mendapat satu rentang; angka berapa pun sah asalkan antar user tidak tumpang tindih.awk -F: '{printf ...}': memisah kolom pada titik dua; UID terakhir rentang dihitung$2+$3-1, yaitu awal ditambah jumlah dikurangi satu.- Makna pemetaan: UID 0 di dalam container budi sebenarnya adalah budi di host, dan UID 1 sampai 65535 di dalam container dipetakan ke rentang 100000 ke atas.
Hasilnya dua lapis keuntungan. Pertama, proses root di dalam container tidak pernah menjadi root di host — satu lubang sekalipun prosesnya lolos keluar, yang ditemukannya tetap akun budi. Kedua, file yang ditulis root di dalam container jelas dimiliki budi di host — data database bisa dibaca tanpa sudo. Bandingkan dengan mode rootful, tempat root container benar-benar root host: satu celah keluar langsung berakhir di akun paling kuat.
Pod: Beberapa Container Satu Rumah #
Pod adalah satu unit yang berisi beberapa container berbagi namespace — jaringan yang sama, alamat IP yang sama, bahkan localhost yang sama. Konsepnya diadopsi dari Kubernetes: satu pod membawa satu tugas logis yang terdiri dari beberapa proses. Pattern klasiknya sidecar: aplikasi utama dan container kecil pengirim log di sebelahnya saling bicara lewat localhost tanpa jaringan virtual apa pun.
Beda konsepnya dengan Compose penting dipahami: compose menyatukan container-container yang terpisah lewat jaringan dan DNS; pod menyatukan container yang berbagi rumah.
| Aspek | Pod | Docker Compose |
|---|---|---|
| Hubungan antar container | satu network namespace, saling lewat localhost | jaringan virtual, saling lewat nama DNS |
| Wujud deklarasi | manifest Kubernetes-style YAML | docker-compose.yml |
| Cocok untuk | sidecar — proses yang padu (app + log shipper) | aplikasi multi-service utuh (web + db + cache) |
Dua perintahnya: podman pod create --name toko --publish 8080:80 membuat pod kosong dengan port milik pod itu sendiri, lalu podman run --pod toko ... memasukkan container ke dalamnya. Port di-publish sekali di pod, bukan per container — karena memang seluruh pod berbagi satu stack jaringan.
Ekosistem dan Integrasi systemd #
Podman tidak berdiri sendiri; tiga alat satu keluarga membagi tugas yang di Docker dipegang satu daemon:
| Alat | Tugas |
|---|---|
podman | menjalankan dan mengelola container |
buildah | membangun image tanpa daemon, langkah demi langkah, dari script sekalipun |
skopeo | menyalin dan memeriksa image antar registry tanpa menjalankan container |
Untuk compose file yang sudah ada, podman-compose membacanya dan menjalankan tiap service lewat podman. Kontinuitas Dockerfile juga terjaga — berkas Containerfile berikut tersedia di bundle materi ini:
cat Containerfile
echo '== audit cepat =='
echo '-- FROM (versi dipin):'
head -1 Containerfile
echo '-- USER (non-root):'
grep '^USER' Containerfile
echo '-- CMD (bentuk exec, bukan shell):'
grep '^CMD' ContainerfileOutput yang Dihasilkan:
FROM docker.io/library/debian:12-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 \
&& rm -rf /var/lib/apt/lists/*
COPY server.py /app/server.py
USER 1000:1000
WORKDIR /app
CMD ["python3", "server.py"]
== audit cepat ==
-- FROM (versi dipin):
FROM docker.io/library/debian:12-slim
-- USER (non-root):
USER 1000:1000
-- CMD (bentuk exec, bukan shell):
CMD ["python3", "server.py"]Mari kita bedah Containerfile baris demi baris:
FROM docker.io/library/debian:12-slim: image dasar dipin ke versi spesifik; prefiksdocker.io/library/adalah nama registry lengkap yang selalu ditampilkan podman — tidak ada image “anonim”.RUN apt-get ... && rm -rf /var/lib/apt/lists/*: satu layer untuk pasang dan bersih-bersih — cache paket tidak ikut menggembungkan image.COPY server.py /app/server.py: hanya satu berkas yang disalin;WORKDIR /appmenetapkan direktori kerja setelahnya.USER 1000:1000: proses berjalan sebagai UID 1000, bukan root — kebiasaan yang dibedah tuntas di Chapter Container Security .CMD ["python3", "server.py"]: bentuk exec form — proses berjalan sebagai PID 1 tanpa shell pembungkus.
Satu kekosongan arsitektur daemonless tetap harus diisi: pada Docker, daemon-lah yang membangkitkan ulang container mati lewat --restart. Tanpa daemon, tugas itu pulang ke alat yang memang ahlinya — systemd. Dua jalurnya: podman generate systemd membuat unit dari container yang sedang jalan, atau Quadlet — berkas .container kecil yang ditaruh di ~/.config/containers/systemd/. Berkas web-toko.container di bundle materi adalah Quadlet:
cat web-toko.containerOutput yang Dihasilkan:
[Unit]
Description=Web toko (nginx dalam container)
[Container]
Image=docker.io/library/nginx:1.27
PublishPort=8080:80
[Service]
Restart=always
[Install]
WantedBy=default.targetIsinya sebagai berikut:
[Container]:ImagedanPublishPort— padanan persispodman run -d --publish 8080:80 docker.io/library/nginx:1.27.[Service] Restart=always: kebangkitan ulang dipegang systemd, menggantikan--restart=alwaysmilik daemon.[Install] WantedBy=default.target: target user, bukanmulti-user.targetsistem — karena container ini rootless, unit-nya juga milik user.- Cara pakainya:
systemctl --user daemon-reloadlalusystemctl --user start web-toko— container menjadi service biasa yang ikut di-boot bersama sesi user.
Podman menjawab dua keberatan lama terhadap container — daemon dan root — tanpa mengubah cara kita berpikir tentang image dan Containerfile. Arah berikutnya menyelam ke lapisan yang selama ini kita perlakukan sebagai kotak hitam: ketika web memanggil db dengan nama, siapa yang menjawab panggilan itu? Chapter Container Networking
membedah bridge, NAT, dan DNS di balik layar.
Referensi lanjut: dokumentasi Podman untuk referensi lengkap perintah dan konfigurasi, serta situs Podman untuk pengantar arsitektur daemonless-nya.