Lewati ke konten utama
  1. Docker/

Mengecilkan Docker Image dengan Multi-Stage Builds

Penulis
GezyTech
Menulis tentang AI, Linux, Server, Docker, dan teknologi lainnya.

TLDR
#

Docker image sering gemuk karena menyertakan seluruh toolchain build (compiler, dependency dev, source) padahal yang dibutuhkan produksi hanyalah artefak akhir. Multi-stage build memisahkan proses build dan runtime ke dalam dua tahap, sehingga image final hanya berisi yang benar-benar diperlukan — bisa memangkas ukuran dari ratusan MB jadi puluhan MB.


Pendahuluan
#

Image Docker yang besar memperlambat pull, memakan disk, dan memperluas permukaan serangan. Penyebab paling umum: semua yang dipakai saat build (compiler, SDK, dependency development) ikut terbawa ke image produksi.

Multi-stage build adalah solusinya. Kamu memakai satu FROM untuk tahap build, lalu FROM kedua untuk tahap runtime, dan hanya menyalin artefak yang diperlukan.


Contoh Tanpa Multi-Stage (Gemuk)
#

Contoh aplikasi Go sederhana:

FROM golang:1.22

WORKDIR /app
COPY . .
RUN go build -o myapp .

CMD ["./myapp"]

Masalahnya: image ini mengandung seluruh toolchain Go (ratusan MB) padahal aplikasi yang berjalan hanya butuh binary hasil build.


Versi Multi-Stage (Ramping)
#

# Tahap 1: build
FROM golang:1.22 AS builder

WORKDIR /app
COPY . .
RUN go build -o myapp .

# Tahap 2: runtime
FROM alpine:3.20

WORKDIR /app
COPY --from=builder /app/myapp .

CMD ["./myapp"]

Perbedaannya besar:

Image Ukuran khas
golang:1.22 (tanpa multi-stage) ~800 MB
alpine + binary (multi-stage) ~15 MB

Konsep Utama
#

AS — memberi nama tahap
#

FROM node:20 AS builder

COPY --from — menyalin antar tahap
#

COPY --from=builder /app/dist /usr/share/nginx/html

Kamu bisa menyalin dari tahap mana pun yang sudah diberi nama.


Contoh Node.js
#

Tanpa optimasi
#

FROM node:20

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

CMD ["node", "dist/index.js"]

Multi-stage
#

# Tahap build
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Tahap runtime
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --omit=dev
CMD ["node", "dist/index.js"]

npm ci --omit=dev hanya menginstal dependency produksi, bukan dependency development.


Contoh Python
#

# Tahap build
FROM python:3.12 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Tahap runtime
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY app/ ./app
CMD ["python", "-m", "app"]

Tips Optimasi Lanjutan
#

Teknik Efek
Pilih base image minimal (alpine, slim) Kurangi ukuran drastis
Pisahkan COPY package.json dulu Manfaatkan cache layer
npm ci bukan npm install Install deterministik & cepat
--no-cache-dir (pip) Hindari cache pip
.dockerignore Jangan salin file tak perlu
Gabungkan perintah RUN Kurangi jumlah layer

.dockerignore
#

Buat file .dockerignore:

node_modules
.git
*.log
.env

File yang di-ignore tidak ikut terkirim ke build context, mempercepat build dan menjaga image bersih.


Memeriksa Ukuran Image
#

docker images

Bandingkan ukuran sebelum dan sesudah multi-stage. Untuk melihat riwayat layer:

docker history nama-image

Troubleshooting
#

Binary tidak bisa dijalankan di alpine
#

Aplikasi yang di-build dengan glibc (misal Go tanpa CGO) biasanya aman di alpine. Tapi jika error not found, coba:

FROM debian:bookworm-slim

atau aktifkan CGO_ENABLED=0 saat build.

Dependency hilang di tahap runtime
#

Pastikan menyalin semua artefak yang dibutuhkan runtime (bukan hanya source), misalnya node_modules produksi atau library sistem.

Cache layer tidak berfungsi
#

Urutan COPY memengaruhi cache. Salin file yang jarang berubah (seperti package.json) lebih dulu.


Ringkasan
#

Konsep Inti
FROM ... AS name Definisikan tahap build
COPY --from=name Salin artefak ke tahap runtime
Base minimal alpine / slim
.dockerignore Kurangi build context

Dokumentasi: docs.docker.com/build/building/multi-stage/