Struktur Dockerfile #
Dockerfile adalah blueprint utama dalam proses membangun Docker Image. Setiap instruksi di dalam Dockerfile dieksekusi secara berurutan dan membentuk layer yang menentukan ukuran, performa, keamanan, serta maintainability image yang dihasilkan.
Bagi backend engineer, DevOps, maupun platform engineer, memahami struktur Dockerfile bukan hanya soal bisa build image, tetapi:
- memahami bagaimana layer bekerja
- menghindari image yang terlalu besar
- menjaga keamanan kredensial
- mempercepat build dan deployment
Bagan Struktur Dockerfile (Konseptual) #
┌──────────────────────────┐
│ FROM │ ← Base Image
├──────────────────────────┤
│ ARG │ ← Build-time Variable
├──────────────────────────┤
│ ENV │ ← Runtime Environment Variable
├──────────────────────────┤
│ WORKDIR │ ← Working Directory
├──────────────────────────┤
│ COPY / ADD │ ← Copy Source Code / Asset
├──────────────────────────┤
│ RUN │ ← Install Dependencies / Build
├──────────────────────────┤
│ EXPOSE │ ← Port Documentation
├──────────────────────────┤
│ USER │ ← Runtime User
├──────────────────────────┤
│ ENTRYPOINT / CMD │ ← Container Startup Command
└──────────────────────────┘
Bagan di atas menunjukkan urutan logis Dockerfile dari atas ke bawah, meskipun dalam praktik beberapa instruksi bisa diulang atau dikombinasikan.
Konsep Dasar Dockerfile #
- Dockerfile adalah file deklaratif
- Setiap instruksi menghasilkan immutable layer
- Perubahan pada satu layer akan meng-invalidate cache layer setelahnya
Implikasinya:
- Urutan instruksi sangat penting
- Kesalahan kecil bisa berdampak ke ukuran dan waktu build
FROM #
Fungsi #
Menentukan base image yang akan digunakan.
Aturan Penting #
- Instruksi pertama wajib FROM (kecuali ARG sebelum FROM)
- Bisa digunakan lebih dari satu kali (multi-stage build)
Contoh #
FROM golang:1.22-alpine
Multi-stage 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 app
FROM gcr.io/distroless/base-debian12
WORKDIR /app
COPY --from=builder /app/app .
CMD ["/app/app"]
ARG #
Fungsi #
Mendefinisikan variable yang hanya tersedia saat build.
Karakteristik #
- Tidak tersedia saat container runtime
- Bisa di-override dengan
--build-arg
Contoh #
ARG APP_ENV=production
ARG GO_VERSION=1.22
FROM golang:${GO_VERSION}-alpine
ENV #
Fungsi #
Mendefinisikan environment variable saat runtime.
Contoh #
ENV APP_ENV=production
ENV APP_PORT=8080
Perbedaan ARG vs ENV #
| Aspek | ARG | ENV |
|---|---|---|
| Waktu hidup | Build time | Runtime |
| Bisa diakses container | ❌ | ✅ |
| Aman untuk secret | ❌ | ❌ |
WORKDIR #
Fungsi #
Menentukan direktori kerja di dalam container.
Best Practice #
- Gunakan WORKDIR dibanding
cddi RUN
Contoh #
WORKDIR /app
COPY #
Fungsi #
Menyalin file dari host ke image.
Contoh #
COPY . .
COPY go.mod go.sum ./
Best Practice #
- Copy file dependency dulu agar cache efektif
ADD #
Fungsi Tambahan dibanding COPY #
- Bisa extract tar otomatis
- Bisa download URL (tidak direkomendasikan)
Contoh #
ADD archive.tar.gz /app
Rekomendasi #
Gunakan COPY, kecuali butuh fitur khusus ADD.
RUN #
Fungsi #
Menjalankan perintah saat build image.
Contoh #
RUN apk add --no-cache ca-certificates
Menggabungkan Command #
RUN apk add --no-cache \
git \
curl \
&& rm -rf /var/cache/apk/*
EXPOSE #
Fungsi #
Dokumentasi port yang digunakan aplikasi.
Contoh #
EXPOSE 8080
EXPOSE tidak membuka port, hanya dokumentasi.
USER #
Fungsi #
Menentukan user yang digunakan container.
Contoh #
RUN adduser -D appuser
USER appuser
Alasan Penting #
- Menghindari running sebagai root
- Meningkatkan keamanan
VOLUME #
Fungsi #
Mendeklarasikan mount point untuk data persisten.
Contoh #
VOLUME ["/data"]
HEALTHCHECK #
Fungsi #
Menentukan mekanisme health monitoring container.
Contoh #
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
SHELL #
Fungsi #
Mengubah shell default untuk RUN.
Contoh #
SHELL ["/bin/bash", "-c"]
ONBUILD #
Fungsi #
Menentukan trigger untuk image turunan.
Contoh #
ONBUILD COPY . /app
Catatan #
Jarang digunakan, rawan membingungkan.
STOPSIGNAL #
Fungsi #
Menentukan signal untuk menghentikan container.
Contoh #
STOPSIGNAL SIGTERM
CMD #
Fungsi #
Menentukan perintah default saat container dijalankan.
Contoh #
CMD ["./app"]
Karakteristik #
- Bisa dioverride
docker run
ENTRYPOINT #
Fungsi #
Menentukan executable utama container.
Contoh #
ENTRYPOINT ["./app"]
ENTRYPOINT + CMD #
ENTRYPOINT ["./app"]
CMD ["--help"]
Perbedaan CMD vs ENTRYPOINT #
| Aspek | CMD | ENTRYPOINT |
|---|---|---|
| Bisa dioverride | Ya | Sulit |
| Cocok untuk | Default command | Binary utama |
Best Practice #
1. Gunakan Base Image Sekecil Mungkin #
- alpine
- distroless
2. Manfaatkan Multi-stage Build #
- Pisahkan build dan runtime
- Image lebih kecil & aman
3. Optimalkan Cache #
- COPY dependency sebelum source code
4. Jangan Simpan Secret #
❌ Jangan:
ENV DB_PASSWORD=secret
Gunakan:
- Docker secrets
- Environment runtime
5. Jangan Jalankan Sebagai Root #
Gunakan USER non-root.
6. Minimalkan Layer #
- Gabungkan RUN
- Hapus cache package manager
7. Tambahkan HEALTHCHECK #
Agar orchestration lebih cerdas.
Penutup #
Dockerfile bukan sekadar file konfigurasi, tetapi fondasi kualitas Docker Image. Dengan memahami setiap instruksi, implikasi layer, dan best practice, kita bisa menghasilkan image yang:
- kecil
- cepat
- aman
- siap produksi
Pemahaman Dockerfile yang baik adalah skill fundamental bagi engineer modern—terutama di era cloud-native dan container orchestration.