Membuat image container sendiri dengan Containerfile dan Buildah: memahami direktif FROM, RUN, COPY, CMD, ENTRYPOINT, dan HEALTHCHECK, membangun dengan podman build beserta cache dan build context, menjalankan buildah bud tanpa daemon, serta eksekusi build multi-stage.

Selama delapan episode kalian memakai image yang sudah jadi dari registry. Episode 9 ini mengajarkan cara membuat image sendiri — mulai dari menulis Containerfile, membangun dengan podman build, sampai memakai Buildah untuk pendekatan yang lebih granular dan tanpa daemon. Inilah keterampilan yang mengubah kalian dari konsumen image menjadi produsen image.
Podman menerima dua nama file: Containerfile dan Dockerfile. Keduanya adalah file teks dengan format yang sama; hanya namanya yang berbeda. Containerfile menjadi preferensi ekosistem Podman, sementara Dockerfile ada untuk kompatibilitas. Podman mencari Containerfile terlebih dahulu, lalu Dockerfile.
Isi file ini berupa sederetan direktif yang dieksekusi berurutan. Setiap direktif menghasilkan satu lapisan (layer) baru dalam image:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Setiap lapisan menyimpan delta dari lapisan sebelumnya — struktur berlapis inilah yang memungkinkan cache build dan berbagi layer antar image.
Direktif yang paling sering dipakai dijelaskan di tabel berikut:
| Direktif | Fungsi | Contoh |
|---|---|---|
FROM | Menentukan image dasar | FROM python:3.12-slim |
RUN | Menjalankan perintah saat build | RUN apt-get update |
COPY | Menyalin file dari build context | COPY . /app |
CMD | Perintah default saat container jalan | CMD ["node", "app.js"] |
ENTRYPOINT | Perintah tetap yang tidak bisa ditimpa | ENTRYPOINT ["python"] |
HEALTHCHECK | Memeriksa kesehatan container | HEALTHCHECK CMD curl -f ... |
FROM harus menjadi direktif pertama. RUN mengeksekusi perintah dan menyimpan hasilnya sebagai layer. COPY menyalin file dari direktori build context ke dalam image.
Pasangan CMD dan ENTRYPOINT sering membingungkan. ENTRYPOINT adalah perintah yang selalu berjalan dan tidak bisa diganti — ia menetapkan cara program dijalankan. CMD adalah argumen default yang bisa diganti oleh argumen di podman run. Jika ENTRYPOINT ditetapkan, nilai CMD menjadi argumen bagi ENTRYPOINT:
| Skenario | Hasil eksekusi |
|---|---|
Hanya CMD | podman run image menjalankan CMD; argumen run menggantinya |
Hanya ENTRYPOINT | Selalu menjalankan ENTRYPOINT |
| Keduanya | Menjalankan ENTRYPOINT dengan CMD sebagai argumen default |
HEALTHCHECK memberi tahu Podman cara memastikan container masih sehat — berguna untuk orkestrasi dan monitoring, dan akan kembali dibahas pada episode observability nanti.
Perintah build cukup sederhana; bagian terpentingnya adalah build context — direktori yang disalin menjadi area kerja build dan menjadi sumber bagi COPY:
podman build -t myapp:latest .
podman build -t myapp:latest ./srcpodman build -t myapp:latest . membangun image dengan tag myapp:latest dari build context direktori saat ini. -t bisa dipakai berulang untuk beberapa tag sekaligus. podman build -t myapp:latest . memakai Buildah di balik layar untuk melaksanakan build, sehingga prosesnya tidak membutuhkan daemon — konsisten dengan arsitektur yang dipelajari sejak episode 1.
Layer yang sudah pernah dibangun dan tidak berubah akan di-cache dan dipakai ulang. Ini membuat build kedua jauh lebih cepat:
podman build -t myapp:latest .
podman build -t myapp:latest . --cache-from myapp:latestCache bekerja berbasis urutan direktif: jika sebuah RUN berubah, layer setelahnya ikut dibangun ulang. Karena itu, letakkan direktif yang jarang berubah (seperti instalasi dependency) di bagian atas, dan yang sering berubah (seperti COPY kode aplikasi) di bawah — strategi sederhana ini memangkas waktu build secara dramatis.
Build multi-stage memakai beberapa direktif FROM dalam satu Containerfile. Tahap akhir hanya mengambil artefak yang dibutuhkan, menghasilkan image final yang jauh lebih kecil:
FROM golang:1.24 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /app/server .
FROM alpine:latest
COPY --from=builder /app/server /usr/local/bin/server
EXPOSE 8080
CMD ["server"]Tahap builder mengkompilasi program Go; tahap kedua menyalin hasil build --from=builder ke image berbasis Alpine yang ringkas. Toolchain lengkap tidak ikut terbawa ke image final — inilah inti dari build multi-stage: image produksi berisi hasil, bukan alat build.
Tip
Gunakan tag distro yang eksplisit, misalnya alpine:latest atau golang:1.24, dan perbarui secara berkala. Image yang tidak pernah di-pull ulang akan menumpuk CVE lama; kebiasaan membangun ulang dari base image yang terbarui adalah lapisan keamanan yang murah.
Buildah adalah saudara Podman yang fokus pada pembangunan image. Podman memakainya secara internal, tetapi Buildah juga bisa dipakai langsung dengan gaya yang lebih granular. buildah bud setara dengan podman build:
buildah bud -t myapp:latest .Selain bud, Buildah menawarkan gaya imperatif: setiap langkah dijalankan satu per satu dari container kerja:
buildah from --name builder alpine:latest
buildah copy builder ./server /usr/local/bin/server
buildah run builder -- sh -c "chmod +x /usr/local/bin/server"
buildah commit builder myapp:latestbuildah from memulai container kerja, buildah copy menyalin file, buildah run mengeksekusi perintah, dan buildah commit mengabadikan hasilnya menjadi image. Pendekatan ini berguna saat logika build terlalu kompleks untuk direpresentasikan sebagai direktif statis — kalian mengontrol setiap langkah layaknya skrip.
| Alat | Fokus utama | Perintah kunci |
|---|---|---|
| Podman | Menjalankan dan mengelola container | podman build, podman run |
| Buildah | Membangun image dengan kontrol granular | buildah bud, buildah commit |
| Skopeo | Memeriksa dan memindahkan image | skopeo inspect, skopeo copy |
Ketiganya berbagi format image OCI dan storage yang sama, sehingga image yang dibangun Buildah langsung dipakai podman run tanpa konversi. podman build pada dasarnya adalah jalur nyaman menuju kemampuan Buildah.
Setelah image jadi, verifikasi dengan perintah yang sudah kalian kuasai:
podman images myapp:latest
podman history myapp:latest
podman run -d -p 8080:8080 --name myapp myapp:latestpodman images memastikan image terdaftar, podman history menunjukkan lapisan-lapisan build — berguna untuk menilai ukuran image — dan podman run menjalankannya dengan pola yang sudah familier dari episode 3.
Episode 9 membahas pembangunan image: perbedaan Containerfile dan Dockerfile, direktif FROM, RUN, COPY, CMD, ENTRYPOINT, dan HEALTHCHECK, build dengan podman build beserta cache dan build context, build multi-stage untuk image yang ramping, serta Buildah sebagai jalur build yang lebih granular lewat buildah bud dan perintah imperatif.
Inti yang harus dibawa pulang:
podman build — dan bisa dipakai langsung saat butuh kontrol penuh.Di episode 10 berikutnya, kalian membawa container ke level layanan: Quadlet dan integrasi systemd — unit .container, .pod, .volume, dan .image yang deklaratif, auto-start, restart policy, sampai socket activation dan podman generate systemd.