๐Ÿ‡ฎ๐Ÿ‡ฉ Bahasa Indonesia

Docker Multi-Stage Build: Panduan Lengkap untuk Pemula (2026)

Belajar Docker multi-stage build dari nol โ€” perkecil image 10x, hapus dependencies build, dan deploy container ringan ke production.

29 June 2026ยท6 min readยท
#docker#multi-stage#container

Pengantar

Image Docker pada umumnya terlalu besar. Aplikasi Node.js bisa mencapai 1,2 GB. Binary Go bisa 800 MB. Sebagian besar ukuran itu berasal dari tool build, dependency development, dan package sistem operasi yang tidak seharusnya ada di container production.

Docker multi-stage build adalah teknik yang memisahkan environment build dari environment runtime. Kamu meng-compile aplikasi di container besar yang berisi semua tool, lalu menyalin hanya artifact akhir ke image runtime yang minimal.

Hasilnya: image 10x sampai 50x lebih kecil, lebih cepat di-deploy, dan lebih aman karena surface attack-nya berkurang drastis.

Cara Kerja Multi-Stage Build

Dockerfile multi-stage memiliki beberapa pernyataan FROM. Setiap FROM memulai stage baru. Kamu bisa menyalin artifact dari stage sebelumnya ke stage berikutnya, meninggalkan semua yang tidak diperlukan.

Contoh Dasar: Aplikasi Go

# Stage 1: Build
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .

# Stage 2: Runtime
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/server /server
EXPOSE 8080
CMD ["/server"]

Stage pertama (builder) berisi Go compiler, modul, dan source code โ€” sekitar 800 MB. Stage kedua (runtime) hanya berisi binary hasil kompilasi dan certificate root CA โ€” kurang dari 15 MB.

Perhatikan direktif COPY --from=builder. Ini adalah kunci multi-stage: kamu menyalin file spesifik dari stage sebelumnya. Semua yang lain โ€” compiler, dependency, source code โ€” dibuang.

Kenapa Ini Penting: Perbandingan Ukuran

AplikasiDockerfile BiasaMulti-StagePenghematan
Go REST API820 MB13 MB98%
Node.js Express1,2 GB150 MB87%
Python Flask920 MB120 MB87%
Rust Actix1,5 GB15 MB99%

Image kecil berarti deploy lebih cepat, skala lebih cepat, dan keamanan lebih baik karena lebih sedikit package berisi lebih sedikit CVE.

Pattern Build + Test + Runtime

Pattern paling powerful menggunakan tiga stage:

# Stage 1: Dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --production

# Stage 2: Build + Test
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
RUN npm test

# Stage 3: Production Runtime
FROM node:20-alpine AS runtime
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]

Stage deps meng-install dependency production saja. Stage builder menjalankan build dan test โ€” dependency development ada di sini tapi TIDAK ikut ke stage berikutnya. Stage runtime hanya berisi dependency production, hasil build, dan package.json. Tidak ada TypeScript compiler, tidak ada Jest, tidak ada ESLint.

Untuk panduan lengkap CI/CD yang mengintegrasikan pipeline build ini, baca panduan CI/CD untuk Docker di DevToCash.

5 Best Practices Multi-Stage Build

1. Gunakan Alpine untuk Runtime

FROM node:20-alpine AS runtime

Alpine Linux hanya seukuran 5 MB. Dibandingkan dengan Debian-based image (180 MB+), penghematannya signifikan. Trade-off: Alpine menggunakan musl libc, bukan glibc. Untuk binary yang dikompilasi dengan CGO_ENABLED=1, gunakan Alpine dengan hati-hati โ€” CGO_ENABLED=0 selalu lebih aman.

2. Urutkan Layer dari yang Paling Jarang Berubah

Docker me-cache setiap layer. Layer yang jarang berubah sebaiknya di posisi atas:

# Paling jarang berubah โ€” di-cache hampir selamanya
FROM node:20-alpine AS runtime

# Jarang berubah โ€” di-cache berminggu-minggu
RUN apk add --no-cache curl

# Sering berubah โ€” di-cache per build
COPY package.json package-lock.json ./
RUN npm ci --production

# Paling sering berubah โ€” tidak pernah di-cache
COPY . .

Urutan ini memaksimalkan cache hit. Mengubah satu baris kode hanya meng-invalidate layer COPY . . โ€” semua layer di atasnya tetap dari cache.

3. Jangan Copy .git atau node_modules

Gunakan .dockerignore:

.git
node_modules
dist
.env
*.log

Tanpa .dockerignore, COPY . . akan menyalin direktori .git (bisa ratusan MB), node_modules lokal (mungkin berbeda OS), dan file environment. Selalu tambahkan .dockerignore sebelum menulis Dockerfile.

4. Gunakan Non-Root User

FROM alpine:3.19
RUN adduser -D -g '' appuser
COPY --from=builder /app/server /server
USER appuser
CMD ["/server"]

Container production tidak boleh berjalan sebagai root. Jika attacker berhasil escape dari container, mereka tidak mendapatkan akses root di host.

5. Multi-Stage dengan Multiple Binary

Untuk monorepo yang menghasilkan beberapa binary:

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o /bin/api ./cmd/api
RUN go build -o /bin/worker ./cmd/worker

FROM alpine:3.19 AS api
COPY --from=builder /bin/api /api
CMD ["/api"]

FROM alpine:3.19 AS worker
COPY --from=builder /bin/worker /worker
CMD ["/worker"]

Satu stage builder menghasilkan dua binary. Dua stage runtime terpisah โ€” masing-masing hanya berisi binary yang dibutuhkan.

Debugging Multi-Stage Build

Kalau build gagal, kamu bisa menjalankan stage tertentu untuk debugging:

# Build sampai stage builder dan berhenti
docker build --target builder -t debug-image .

# Jalankan shell di dalamnya
docker run -it debug-image sh

Ini memungkinkan kamu melihat isi stage builder โ€” apakah binary ter-compile dengan benar? Apakah dependency ter-install? โ€” tanpa harus menyelesaikan seluruh Dockerfile.

Perbandingan: Single-Stage vs Multi-Stage

Single-stage (JANGAN dilakukan):

FROM node:20
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
EXPOSE 3000
CMD ["node", "dist/server.js"]

Masalah: Image ini berisi seluruh source code, node_modules (termasuk devDependencies), npm cache, dan OS Debian lengkap. Ukuran: ~1 GB. Attack surface: besar. Deploy time: lambat.

Multi-stage (LAKUKAN ini):

Seperti contoh di atas โ€” dependency production saja, binary hasil build saja, Node.js runtime saja. Ukuran: ~150 MB. Attack surface: kecil. Deploy time: cepat.

Integrasi dengan Kubernetes

Untuk tim yang mendeploy ke Kubernetes, image kecil punya dampak langsung pada performa cluster. Kami membahas optimasi Kubernetes dari sisi keamanan dan resource di panduan Kubernetes Security Best Practices. Gabungkan multi-stage build untuk image kecil dengan resource limits dan network policies untuk deployment yang production-ready.

Baca juga panduan Dagger CI/CD untuk DevOps yang membahas otomatisasi build pipeline modern.

Mulai Sekarang

Multi-stage build adalah teknik fundamental yang harus dikuasai setiap developer. Tidak ada alasan untuk mendeploy image 1 GB ke production di tahun 2026.

Langkah selanjutnya:

  • Subscribe newsletter DevToCash untuk panduan DevOps mingguan dalam Bahasa Indonesia โ€” dari Docker dasar sampai Kubernetes production.
  • Baca panduan Docker Multi-Stage Builds lengkap untuk contoh lebih banyak (Node.js, Python, Java, Rust).
  • Pelajari panduan CI/CD pemula untuk mengotomatisasi build pipeline dari git push hingga production.

Punya pertanyaan tentang multi-stage build? Drop komentar di bawah atau DM kami di LinkedIn. Selamat building! ๐Ÿณ

#docker#multi-stage#container#devops#nodejs#golang#tutorial
D
DevToCashAuthor

Senior DevOps/SRE Engineer ยท 10+ years ยท Professional Trader (IDX, Crypto, US Equities)

I write about real infrastructure patterns and trading strategies I use in production and in live markets. No courses, no affiliate hype โ€” just documentation of what actually works.

More about me โ†’