Best Practice #

Docker image adalah fondasi dari seluruh ekosistem container. Image yang buruk akan berdampak langsung pada keamanan, ukuran, kecepatan build, waktu startup, dan stabilitas di production. Sebaliknya, Docker image yang dirancang dengan baik akan membuat deployment lebih cepat, scaling lebih efisien, dan operasional lebih tenang.

Artikel ini membahas best practice Docker image secara menyeluruh, tidak terikat pada bahasa pemrograman tertentu, dan relevan untuk aplikasi modern (monolith, microservice, hingga serverless container).

Prinsip Dasar Docker Image yang Baik #

Sebelum masuk ke teknis, ada beberapa prinsip fundamental:

  1. Small is better – image kecil lebih cepat ditarik dan lebih aman
  2. Immutable – image tidak diubah setelah dibuild
  3. Single responsibility – satu image = satu tujuan utama
  4. Secure by default – minim permission, minim attack surface
  5. Reproducible – build harus konsisten di mana pun

Semua best practice di bawah berakar dari prinsip-prinsip ini.


Memilih Base Image dengan Bijak #

Gunakan Base Image Sekecil Mungkin #

Hindari base image besar kecuali benar-benar dibutuhkan.

Urutan preferensi umum:

  • scratch
  • distroless
  • alpine
  • debian-slim
  • ubuntu

Semakin ke bawah, semakin besar attack surface dan ukuran image.

Pahami Konsekuensi Alpine #

Alpine sangat populer, tetapi:

  • Menggunakan musl libc (bukan glibc)
  • Beberapa binary/library bisa bermasalah
  • Debugging lebih sulit

Gunakan Alpine jika:

  • Aplikasi statically linked
  • Dependensi minimal
  • Sudah teruji di production

Gunakan Multi-Stage Build #

Multi-stage build adalah best practice wajib.

Masalah Tanpa Multi-Stage #

  • Image membawa compiler
  • Image membawa source code
  • Image membawa cache build

Solusi Multi-Stage #

Konsepnya:

  1. Stage pertama: build
  2. Stage terakhir: runtime saja

Hasilnya:

  • Image jauh lebih kecil
  • Lebih aman
  • Lebih bersih

Multi-stage build juga memudahkan:

  • Cross compilation
  • Optimasi dependency
  • Pemisahan concern build vs runtime

Jangan Jalankan Aplikasi sebagai Root #

Secara default, container berjalan sebagai root. Ini berbahaya.

Best Practice #

  • Buat user non-root
  • Jalankan aplikasi dengan user tersebut

Manfaat:

  • Mengurangi dampak jika container compromise
  • Lebih sesuai dengan security policy Kubernetes
  • Mandatory di beberapa environment enterprise

Minimalkan Layer Docker Image #

Setiap instruksi RUN, COPY, dan ADD menambah layer.

Praktik yang Baik #

  • Gabungkan perintah RUN
  • Bersihkan cache dalam layer yang sama

Contoh konsep:

  • Install dependency
  • Hapus cache
  • Semua dalam satu RUN

Ini menjaga image:

  • Lebih kecil
  • Lebih rapi
  • Lebih cepat ditransfer

Gunakan .dockerignore #

Tanpa .dockerignore, Docker akan:

  • Mengirim seluruh context ke daemon
  • Memperlambat build
  • Berpotensi membocorkan file sensitif

Wajib Dikecualikan #

  • .git
  • node_modules
  • vendor
  • .env
  • File log
  • File build lokal

.dockerignore sama pentingnya dengan .gitignore.


Jangan Simpan Secret di Docker Image #

Kesalahan fatal yang sering terjadi:

  • API key di Dockerfile
  • Credential di ENV saat build
  • File secret dicopy ke image

Best Practice #

  • Inject secret saat runtime

  • Gunakan:

    • Environment variable
    • Secret manager (Kubernetes, AWS, GCP)

Ingat: Docker image bersifat immutable dan mudah di-distribute.


Gunakan Tag Image dengan Benar #

Hindari latest #

latest:

  • Tidak deterministic
  • Sulit rollback
  • Membingungkan saat incident

Strategi Tag yang Baik #

  • Semantic version (1.2.3)
  • Git commit hash
  • Build number

Contoh:

  • app:1.4.0
  • app:1.4.0-rc.1
  • app:git-a1b2c3

Optimasi Dependency #

Install Hanya yang Dibutuhkan #

  • Jangan install tool debug di production image
  • Pisahkan dependency build dan runtime

Audit Dependency #

  • Hapus dependency yang tidak dipakai
  • Hindari “install all” mindset

Dependency berlebih =

  • Image besar
  • Attack surface luas
  • Update security lebih sering

Perhatikan Caching Docker Build #

Docker build cache bisa sangat membantu jika urutan Dockerfile benar.

Prinsip Umum #

  • Instruksi yang jarang berubah di atas
  • Source code di bawah

Ini akan:

  • Mempercepat build
  • Menghemat resource CI/CD

Tambahkan Metadata pada Image #

Gunakan label untuk dokumentasi:

  • Maintainer
  • Source repository
  • Version
  • Description

Manfaat:

  • Observability
  • Audit
  • Traceability

Sangat membantu di environment besar.


Scan Vulnerability Docker Image #

Image kecil ≠ image aman.

Best Practice #

  • Scan image secara rutin
  • Integrasikan ke CI/CD

Yang perlu diperhatikan:

  • CVE OS package
  • CVE dependency aplikasi

Image yang aman adalah image yang terawat, bukan hanya kecil.


Jangan Jadikan Docker Image sebagai VM #

Anti-pattern yang sering muncul:

  • Menjalankan banyak service dalam satu container
  • Menggunakan supervisor
  • Treat container seperti server tradisional

Ingat #

  • Container ≠ VM
  • Satu container = satu proses utama

Ini memudahkan:

  • Scaling
  • Monitoring
  • Recovery

Best Practice untuk Production #

Ringkasan prinsip production-grade Docker image:

  • Gunakan multi-stage build
  • Base image sekecil mungkin
  • Non-root user
  • Tanpa secret di image
  • Tag version dengan jelas
  • Image immutable
  • Scan vulnerability rutin

Jika sebuah image:

  • Kecil
  • Aman
  • Mudah direproduksi

Maka operasional Anda akan jauh lebih stabil.


Penutup #

Docker image bukan sekadar artefak build, tetapi kontrak operasional antara developer, CI/CD, dan runtime environment. Investasi pada best practice Docker image akan membayar dirinya sendiri dalam bentuk:

  • Deployment lebih cepat
  • Incident lebih sedikit
  • Security posture lebih kuat
  • Biaya infra lebih efisien

Dockerfile yang baik adalah tanda tim engineering yang matang.

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact