Mengoptimalkan Docker Image dengan Alpine dan Distroless Base Image
Dampak Ukuran Image terhadap Pipeline Deployment dan Biaya Infrastruktur
Ukuran Docker image memiliki dampak langsung terhadap efisiensi pipeline deployment dan biaya infrastruktur. Setiap kali kita menjalankan CI/CD pipeline, image harus ditarik dari container registry ke node tujuan. Semakin besar image, semakin lama waktu pull yang dibutuhkan. Pada lingkungan dengan banyak microservice, waktu pull yang akumulatif ini bisa memperlambat siklus deployment secara signifikan.
Dari sisi biaya, container registry seperti Docker Hub, Amazon ECR, dan Google Container Registry mengenakan tarif berdasarkan jumlah data yang disimpan. Image berukuran besar berarti storage cost yang lebih tinggi, terutama jika kita menyimpan banyak versi image untuk keperluan rollback. Selain itu, transfer data keluar dari registry juga berkontribusi pada biaya infrastruktur yang membengkak.
Aspek keamanan juga tidak kalah penting. Image yang lebih besar memiliki surface area yang lebih luas — semakin banyak package dan library yang disertakan, semakin banyak potensi vulnerability yang perlu kita pantau. Setiap lapisan tambahan dalam image memperkenalkan risiko keamanan baru. Faktor utama yang menentukan ukuran image adalah base image yang kita pilih. Dengan memilih base image yang tepat, kita bisa mengurangi ukuran image hingga puluhan kali lipat tanpa mengorbankan fungsionalitas.

Gambar: Visualisasi layer Docker image — setiap instruksi (FROM, COPY, RUN) menambahkan layer baru yang bersifat read-only di atas base image, dengan container writable layer di paling atas — Sumber: [Docker Docs](https://docs.docker.com/manuals/engine/storage/drivers/)
Alpine Linux sebagai Base Image Minimalis: Cara Kerja dan Trade-off
Alpine Linux dikenal sebagai distribusi Linux yang sangat ringan, dengan base image hanya sekitar 5 MB — jauh lebih kecil dibandingkan Ubuntu yang bisa mencapai 80 MB atau lebih. Rahasia di balik ukuran kecil ini terletak pada dua keputusan arsitektural utama.
Pertama, Alpine menggunakan musl libc sebagai pengganti glibc yang digunakan oleh hampir semua distribusi Linux mainstream. musl dirancang untuk menjadi implementasi libc yang sederhana, efisien, dan aman. Namun, perbedaan ini membawa konsekuensi: binary yang di-compile menggunakan glibc mungkin tidak kompatibel dengan Alpine. Ini sering menjadi masalah pada wheel Python yang sudah di-precompile, beberapa native Node.js addon, atau binary statis yang bergantung pada fitur tertentu dari glibc.
Kedua, Alpine menggunakan apk sebagai package manager. Repositori Alpine jauh lebih kecil dibandingkan APT milik Debian atau Ubuntu, yang berarti hanya package yang benar-benar esensial yang tersedia. Ini memang menjaga image tetap kecil, tetapi kita mungkin perlu menginstall beberapa dependensi tambahan secara manual.
Mari kita lihat perbandingan konkret dalam Dockerfile:
FROM ubuntu:latest AS ubuntu-base
RUN apt-get update && apt-get install -y curl ca-certificates
COPY app.sh /app.sh
CMD ["bash", "/app.sh"]
FROM alpine:latest AS alpine-base
RUN apk add --no-cache curl ca-certificates
COPY app.sh /app.sh
CMD ["sh", "/app.sh"]Ketika kita build kedua image di atas dan menjalankan docker images, hasilnya akan menunjukkan perbedaan yang mencolok. Image berbasis Ubuntu akan berada di kisaran 100-120 MB, sementara Alpine hanya sekitar 10-15 MB. Perbedaan sepuluh kali lipat ini langsung berdampak pada kecepatan pull dan biaya penyimpanan di registry.
Google Distroless: Base Image Tanpa Lapisan yang Tidak Perlu
Google Distroless membawa konsep minimalisme ke level berikutnya. Jika Alpine masih menyertakan shell, package manager, dan utilitas dasar, Distroless hanya berisi runtime dan aplikasi kita — tidak ada shell, tidak ada package manager, tidak ada utilitas OS. Prinsip ini mirip dengan menyewa mobil tanpa bagasi: hanya yang benar-benar diperlukan untuk berjalan.
Google menyediakan beberapa varian Distroless yang bisa kita pilih: static, base, java, nodejs, dan python3. Masing-masing dirancang untuk runtime tertentu, sehingga tidak ada komponen yang terbuang sia-sia.
Keuntungan utama Distroless adalah keamanan. Tanpa shell, tidak ada cara bagi attacker untuk mendapatkan remote shell access meskipun berhasil mengeksploitasi aplikasi. Ini secara drastis mengurangi permukaan serangan. Di sisi lain, ketiadaan shell membuat debugging menjadi lebih sulit — kita tidak bisa menjalankan docker exec -it <container> bash untuk memeriksa keadaan container.
Berikut adalah contoh implementasi untuk aplikasi Node.js:
Deep Learning Bootcamp
A beginner-friendly, highly interactive bootcamp designed to take you from found...
FROM node:22-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM gcr.io/distroless/nodejs22-debian12
COPY --from=builder /app/dist /app
COPY --from=builder /app/node_modules /app/node_modules
WORKDIR /app
CMD ["app/index.js"]Pada contoh di atas, kita menggunakan node:22-slim sebagai stage builder untuk menginstall dependensi dan membangun aplikasi. Hasil build — folder dist dan node_modules — kemudian disalin ke stage produksi berbasis Distroless. Image akhir hanya berisi runtime Node.js dan file aplikasi, tanpa npm, shell, atau utilitas lain yang tidak diperlukan. Image ini akan berfungsi penuh namun tidak memiliki akses shell sama sekali.
Penerapan Multi-Stage Build untuk Memaksimalkan Alpine dan Distroless
Multi-stage build adalah strategi yang memungkinkan kita menggunakan beberapa FROM statement dalam satu Dockerfile. Stage pertama (builder) menggunakan image penuh dengan toolchain development lengkap. Stage kedua (produksi) menggunakan image minimal seperti Alpine atau Distroless. Artifak hasil build dari stage pertama disalin ke stage produksi menggunakan instruksi COPY --from=builder.
Pendekatan ini memisahkan environment development dari runtime production secara bersih. Toolchain seperti compiler, package manager, dan development dependencies tidak ikut terbawa ke image produksi.

Gambar: Visualisasi dependency graph multi-stage build — stage builder (kiri) menggunakan image lengkap dengan compiler, stage produksi (kanan) hanya menerima binary hasil build melalui COPY --from — Sumber: [dockerfilegraph (MIT License)](https://github.com/patrickhoefler/dockerfilegraph)
Mari kita lihat implementasi lengkapnya untuk aplikasi Go:
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/service .
FROM alpine:3.20
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder /app/service /app/service
EXPOSE 8080
CMD ["/app/service"]
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/service /app/service
EXPOSE 8080
CMD ["/app/service"]Pada pipeline di atas, kita mendefinisikan tiga stage. Stage builder menggunakan golang:1.22-alpine yang memiliki Go compiler lengkap. Kita mengcompile binary secara statis dengan CGO_ENABLED=0, sehingga binary tidak memiliki dependensi eksternal. Stage alpine menambahkan ca-certificates dan tzdata untuk aplikasi yang membutuhkan koneksi HTTPS dan zona waktu tertentu. Stage distroless bahkan lebih minimal dengan hanya berisi binary statis tanpa layer tambahan.
Image akhir yang dihasilkan dari stage distroless bisa berukuran hanya 10-20 MB untuk aplikasi Go, dibandingkan dengan 300-400 MB jika menggunakan golang:1.22 sebagai base image langsung.

Gambar: Ilustrasi bagaimana multiple container dapat berbagi (share) layer image yang sama — semakin kecil base image yang digunakan, semakin hemat storage dan bandwidth saat menjalankan banyak container — Sumber: [Docker Docs](https://docs.docker.com/manuals/engine/storage/drivers/)
Strategi Pemilihan Base Image Berdasarkan Use Case
Tidak ada base image yang sempurna untuk semua situasi. Pemilihan harus disesuaikan dengan kebutuhan spesifik proyek kita.
Image standar seperti ubuntu atau debian masih menjadi pilihan terbaik ketika proyek memiliki native dependencies yang kompleks. Misalnya, aplikasi Python yang menggunakan library seperti psycopg2, numpy, atau pandas sering membutuhkan toolchain kompilasi dan library sistem yang hanya tersedia di image standar. Selain itu, jika tim masih dalam fase development intensif dan sering melakukan debugging langsung di container, image dengan shell dan utilitas akan sangat membantu.
Alpine adalah pilihan tepat untuk aplikasi Go atau Rust yang menghasilkan binary statis, Python project dengan wheel murni tanpa native extension, dan Node.js aplikasi tanpa native addon. Kita perlu memastikan bahwa semua dependencies kompatibel dengan musl sebelum beralih ke Alpine.
Distroless paling cocok untuk production service yang sudah matang dan stabil. Lingkungan dengan compliance ketat seperti PCI-DSS atau HIPAA akan sangat diuntungkan dengan surface area keamanan yang minimal. Distroless juga ideal untuk service yang tidak membutuhkan debugging interaktif.
Pendekatan hybrid sering menjadi solusi terbaik: menggunakan Alpine di environment development untuk kemudahan debugging, dan Distroless di production untuk keamanan maksimal. Dengan multi-stage build, kita bisa menggunakan base image berbeda untuk setiap environment tanpa mengubah struktur aplikasi.
Validasi dan Monitoring Ukuran Image dalam CI/CD Pipeline
Optimasi ukuran image tidak berhenti setelah kita memilih base image yang tepat. Kita perlu mengintegrasikan validasi ukuran ke dalam pipeline CI/CD untuk memastikan image tetap efisien seiring waktu.
Beberapa tools dapat membantu kita dalam proses ini. dive adalah tool open-source yang memungkinkan kita menganalisis layer Docker image secara mendetail. Dengan dive, kita bisa melihat file mana yang menyumbang ukuran terbesar di setiap layer dan mengidentifikasi potensi penghematan.
# Analisis layer image dengan dive
dive myapp:latest
# Quick vulnerability scan dengan Docker Scout
docker scout quickview myapp:latestPerintah dive myapp:latest akan membuka antarmuka interaktif yang menampilkan setiap layer image beserta kontennya. Kita bisa melihat file mana yang tidak perlu dan mencari cara untuk mengeliminasinya. Sementara itu, docker scout quickview memberikan gambaran cepat tentang vulnerability yang ada di image, termasuk severity dan rekomendasi perbaikannya.
Kita juga bisa menerapkan kebijakan ukuran dalam pipeline dengan menetapkan size budget. Jika ukuran image melebihi threshold tertentu, pipeline bisa gagal secara otomatis. Contohnya, kita bisa menambahkan step dalam GitHub Actions atau Jenkins yang menjalankan docker inspect untuk mendapatkan ukuran image, lalu membandingkannya dengan batas yang sudah ditentukan.
Dengan menggabungkan tool analisis seperti dive, scanner keamanan seperti Docker Scout atau Trivy, dan kebijakan size budget dalam pipeline, kita memastikan bahwa optimasi image adalah proses berkelanjutan — bukan sekadar inisiatif satu kali.
Konsep optimasi Docker image menggunakan Alpine, Distroless, dan multi-stage build adalah fondasi penting yang kami ajarkan secara mendalam di sesi Production Container Deployment bootcamp Rumah Coding. Di sana, kita mempraktikkan langsung strategi ini dalam konteks orchestration dan deployment production-grade.
Kursus Terkait
Deep Learning Bootcamp
A beginner-friendly, highly interactive bootcamp designed to take you from foundational concepts to deploying real-world Artificial Intelligence applications. Through a completely project-based approach, you will master the core of Deep Learning, Artificial Neural Networks, and Computer Vision using Python and TensorFlow, ultimately building a professional-grade AI web application for your portfolio.
GreenGuard: Intelligent Plant Disease Diagnosis Web App
- Interactive Image Upload UI: A clean, user-friendly interface built with Streamlit that supports drag-and-drop image uploads directly from a computer or mobile phone.
- Real-Time AI Inference: Utilizes a lightweight, optimized CNN model (like MobileNetV2) to process the image and return a diagnosis in seconds without heavy server load.
- Confidence Scoring Dashboard: Visually displays the model's prediction probability (e.g., "95% confident this is Tomato Late Blight") using interactive progress bars or charts.
LLM Bootcamp
This project-based bootcamp is designed for beginners to dive practically into the world of Large Language Models (LLMs). Through hands-on building, you will learn how to interact with top-tier AI APIs, master prompt engineering, orchestrate complex workflows using LangChain, and implement Retrieval-Augmented Generation (RAG) to query your own documents. By the end of this course, you will have the skills to build, test, and deploy a fully functional, custom AI web application.
Domain-Specific AI Knowledge Assistant
- Dynamic Document Processing: A sidebar interface allowing users to upload new PDF or TXT files, which the app automatically chunks, embeds, and stores in the vector database.
- Context-Aware Chat UI: A modern chat interface built with Streamlit that maintains conversation history, allowing users to ask follow-up questions naturally.
- Strict Guardrails (Anti-Hallucination): System instructions designed so the AI politely declines to answer questions that fall outside the context of the uploaded documents.
Machine Learning Bootcamp
A beginner-friendly, 7-week project-based bootcamp designed to take you from Python basics to deploying your first Machine Learning model. Through hands-on practice, you will master essential data manipulation, build predictive algorithms, and develop an end-to-end, industry-ready application to kickstart your career in data science.
End-to-End Student Success Predictor
- Automated Data Pipeline: A preprocessing script that automatically cleans missing values, encodes categorical data (like course type or student background), and scales numerical inputs.
- Predictive Engine: A tuned machine learning classification model (e.g., Random Forest) specifically optimized for high Recall, ensuring that "at-risk" students are not missed.
- Interactive Web Dashboard: A user-friendly Streamlit interface featuring a sidebar where instructors can manually input a student's study hours, quiz scores, and login frequency to get an instant pass/fail probability.