# Image Docker Distroless: Container Lebih Kecil dan Aman

> Bagaimana image dasar distroless dan multi-stage build memperkecil ukuran image Docker dan permukaan CVE, plus cara debug container yang sama sekali tidak punya shell.

URL: https://www.matthewswong.com/id/blog/docker-distroless-image-optimization/

- Author: Matthews Wong (https://www.matthewswong.com/id/about/)
- Published: 2026-07-05
- Updated: 2026-07-05
- Category: DevOps

Setiap layer yang kamu kirim dalam image Docker produksi adalah permukaan serangan. Base image Debian atau Ubuntu penuh membawa shell, package manager, coreutils, dan puluhan library yang tidak pernah disentuh aplikasimu, dan semuanya menjadi daftar temuan setiap kali vulnerability scanner dijalankan terhadap registry-mu.

Image distroless menghilangkan semua itu, hanya menyisakan runtime bahasa dan shared library yang benar benar dipakai binary-mu. Dipadukan dengan Dockerfile multi-stage, hasilnya adalah image produksi yang lebih kecil, lebih cepat diunduh, dan jauh lebih sedikit temuan pada laporan CVE. Artikel ini membahas cara kerja distroless, cara membangunnya dengan Dockerfile multi-stage, angka ukuran nyata, cara debug container tanpa shell, dan kapan pendekatan ini tidak tepat dipakai.

Apa saja yang benar benar dibuang oleh distroless

Image distroless, yang dirawat oleh proyek container tools milik Google, dibangun di atas satu gagasan: masukkan hanya aplikasimu dan dependensi runtime-nya ke dalam image akhir. Semua hal yang biasanya dibawa distribusi Linux untuk pemakaian interaktif dihilangkan secara sengaja.

Tidak ada binary shell seperti bash atau sh, sehingga tidak ada titik masuk interaktif bagi penyerang yang berhasil mendapatkan eksekusi kode di dalam container

Tidak ada package manager seperti apt atau yum, yang menghilangkan seluruh kategori trik supply chain dan eskalasi privilese

Tidak ada coreutils standar, sehingga perintah umum pasca eksploitasi memang tidak ada di filesystem

Runtime bahasa beserta shared library dan sertifikat CA-nya tetap disertakan, karena aplikasi memang membutuhkannya untuk berjalan dan melakukan panggilan TLS keluar

> Google merilis varian distroless per bahasa: nodejs, python3, java, dan base statis untuk binary Go. Pilih yang cocok dengan runtime-mu daripada mencoba membangun sendiri dari nol di hari pertama.

Membangun dengan Dockerfile multi-stage

Multi-stage build memungkinkan satu Dockerfile memakai beberapa instruksi FROM, satu per stage. Stage pertama mendapat toolchain lengkap: compiler, npm, dependensi development, semua yang dibutuhkan untuk menghasilkan artefak build. Stage terakhir dimulai dari nol dengan base distroless dan hanya menyalin hasil kompilasi, menggunakan instruksi COPY dengan flag from yang menunjuk ke stage sebelumnya lewat nama.

Tidak ada satupun dari stage build yang bocor ke image akhir kecuali kamu menyalinnya secara eksplisit. SDK, berkas sumber TypeScript, dependensi development, dan artefak build sementara tetap tinggal di stage yang dibuang begitu build selesai. Beri nama tiap stage dengan klausa AS agar Dockerfile tetap masuk akal kalau instruksinya diurutkan ulang nanti, dan pertimbangkan flag target saat development lokal supaya kamu bisa membangun dan memeriksa stage build saja tanpa menunggu langkah penyalinan akhir.

Angka ukuran nyata, berdampingan

Angkanya berbeda beda tergantung aplikasi, tapi pola di bawah ini konsisten pada layanan Node.js. Ini adalah perkiraan ukuran image akhir untuk API server kecil yang sama, dibangun dengan tiga cara berbeda.

Base image

Perkiraan ukuran

Catatan

Debian penuh, termasuk seluruh toolchain build yang tidak pernah dibutuhkan aplikasi yang berjalan

Berbasis musl libc, lebih kecil tapi kadang membuat native addon Node yang mengharapkan glibc jadi rusak

Berbasis glibc, tanpa shell atau package manager, paling mendekati jejak runtime sebenarnya

Penurunan ukuran ini penting untuk waktu unduh di setiap deploy dan setiap start pod autoscale, tapi kemenangan yang lebih besar biasanya ada di laporan vulnerability scan. Semakin sedikit paket berarti semakin sedikit CVE yang bisa ditemukan scanner seperti Trivy atau Grype, karena memang tidak ada apa apa yang terpasang untuk dicocokkan dengan database CVE sejak awal.

Debug container yang tidak punya shell

Pertama kali perintah exec masuk lewat bash gagal dengan error entrypoint tidak ditemukan pada container distroless, rasanya membingungkan. Memang tidak ada bash di image itu, dan tidak akan pernah ada, itulah inti dari distroless. Tetap ada tiga cara praktis untuk melakukan debug.

Pakai varian bertanda debug dari image distroless yang sama saat development, yang membawa shell busybox dan bisa dijalankan dengan mengganti entrypoint secara eksplisit, lalu kembali ke tanda non debug untuk deploy sesungguhnya

Pakai perkakas docker debug dari CLI Docker sendiri, yang menyambungkan shell interaktif lengkap dengan utilitas siap pakai seperti vim dan curl ke container yang berjalan atau ke image statis tanpa pernah mengubah image itu sendiri

Reproduksi kegagalannya secara lokal pada stage build di Dockerfile-mu, yang masih punya shell lengkap, karena kebanyakan bug aplikasi muncul identik baik stage akhirnya punya bash ataupun tidak

> Perubahan yang dibuat lewat shell debug yang tersambung ke container yang berjalan tidak pernah tersimpan kembali ke image. Kalau kamu memasang tool atau mengedit berkas untuk menguji sebuah teori, catat apa yang kamu pelajari langsung di Dockerfile, karena container akan kembali ke kondisi semula begitu sesi debug berakhir.

Mengapa permukaan CVE benar benar menyusut

Vulnerability scanner bekerja dengan mencocokkan versi paket yang terpasang terhadap database CVE yang dikenal. Base image OS penuh membawa ratusan paket yang terpasang untuk pemakaian umum, sebagian besar tidak pernah dijalankan aplikasimu tapi tetap saja ditandai begitu CVE baru muncul untuk, misalnya, versi lama sebuah text editor yang tidak pernah dibuka siapapun.

Menghilangkan package manager juga menghilangkan kemampuan penyerang memasang tool baru di tengah serangan, yang secara berarti menaikkan biaya untuk mendapatkan pijakan pasca eksploitasi

Menghilangkan shell menghilangkan cara paling umum penyerang berpindah dari bug eksekusi kode menjadi akses interaktif

Jumlah paket yang lebih kecil berarti lebih sedikit paket yang perlu ditambal dan discan ulang setiap kali update base image dirilis, yang mengurangi beban pemeliharaan berkelanjutan sebanyak pengurangan permukaan serangan awal

Kapan distroless bukan pilihan yang tepat

Distroless bukan tanpa biaya. Tim yang baru memakainya kehilangan waktu di minggu pertama karena kebiasaan debug yang familiar seperti masuk lewat bash berhenti berfungsi, dan dependensi runtime apapun yang dipanggil aplikasimu saat berjalan, seperti memanggil binary sistem lewat child process, harus disertakan secara eksplisit karena tidak akan ada secara default. Kalau timmu deploy cepat dan debug lewat log serta health check level aplikasi ketimbang masuk langsung ke dalam container yang berjalan, biaya transisinya kecil. Kalau proses deploy timmu sangat bergantung pada masuk ke container yang berjalan untuk memeriksa isinya, sisihkan waktu untuk menyesuaikan workflow sebelum menerapkannya secara luas.

> Urutan rollout yang baik: ubah satu layanan dengan traffic rendah ke Dockerfile multi-stage distroless lebih dulu, pastikan logging dan health check-mu memberi sinyal yang cukup tanpa akses shell, baru kemudian terapkan pola ini ke sisa layanan lainnya.

Distroless dipadukan dengan multi-stage build adalah salah satu perubahan berdampak paling besar yang bisa kamu lakukan pada pipeline deploy berbasis Docker. Penurunan ukurannya memang bagus, tapi keuntungan sesungguhnya adalah image produksi yang hampir tidak menyisakan apapun bagi penyerang untuk dipakai setelah masuk, serta laporan vulnerability scan yang benar benar mencerminkan jejak runtime-mu, bukan seluruh distribusi Linux serba guna yang sejak awal tidak pernah kamu butuhkan.

## Sumber

- GoogleContainerTools/distroless — repositori resmi dan katalog image
- Docker Docs — Multi-stage builds
- Docker Docs — referensi docker debug

## Source links

- https://github.com/GoogleContainerTools/distroless
- https://docs.docker.com/build/building/multi-stage/
- https://docs.docker.com/reference/cli/docker/debug/

## FAQ

### Apa itu image Docker distroless?

Image distroless adalah base container minimal yang hanya menyertakan aplikasimu dan dependensi runtime-nya, seperti runtime bahasa, shared library, dan sertifikat CA. Image ini secara sengaja tidak menyertakan shell, package manager, dan utilitas OS standar, itulah yang membuatnya jauh lebih kecil dan lebih sedikit jumlah kerentanannya dibanding base Debian atau Alpine penuh.

### Mengapa memakai distroless dibanding Alpine?

Alpine memang sudah lebih kecil dibanding image OS penuh, tapi tetap membawa shell dan package manager, dan musl libc miliknya bisa diam diam merusak native addon Node atau wheel Python yang mengharapkan glibc. Image distroless berbasis glibc menghilangkan shell dan package manager sepenuhnya sambil tetap menjaga kompatibilitas glibc penuh, yang biasanya berarti lebih sedikit kejutan untuk dependensi yang dikompilasi.

### Bagaimana cara debug container distroless yang tidak punya shell?

Ada tiga cara praktis yang efektif: pakai varian bertanda debug dari image distroless yang sama saat development, yang membawa shell busybox; pakai perintah docker debug milik Docker sendiri, yang menyambungkan toolbox interaktif ke container atau image yang berjalan tanpa mengubahnya; atau reproduksi masalahnya secara lokal pada stage build di Dockerfile-mu, yang masih punya shell lengkap.

### Apakah image distroless bisa dipakai untuk semua bahasa dan framework?

Google merilis varian distroless resmi untuk Node.js, Python, Java, dan base statis untuk bahasa terkompilasi seperti Go, dan ada juga varian yang dirawat komunitas untuk bahasa lain. Kalau aplikasimu memanggil binary sistem saat runtime, seperti memanggil ffmpeg atau imagemagick lewat child process, kamu perlu menyertakan binary tersebut ke dalam image secara eksplisit karena distroless tidak akan menyediakannya secara default.

### Apakah pindah ke distroless benar benar mengurangi jumlah CVE?

Ya, karena vulnerability scanner mencocokkan versi paket yang terpasang dengan database CVE, dan image distroless memang punya jauh lebih sedikit paket terpasang untuk dicocokkan. Menghilangkan package manager dan shell juga menutup cara paling umum yang dipakai penyerang untuk berpindah dari eksekusi kode menjadi akses interaktif di dalam container yang berhasil disusupi.

---

- HTML version: https://www.matthewswong.com/id/blog/docker-distroless-image-optimization/
- English: https://www.matthewswong.com/en/blog/docker-distroless-image-optimization/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
