"Di laptop saya jalan kok" adalah salah satu masalah paling lama di tim software. Developer baru menghabiskan dua hari memasang versi PHP, Node.js, PostgreSQL, dan Redis yang pas, sementara server production menjalankan versi yang sedikit berbeda dari keduanya. Docker membungkus aplikasi beserta semua kebutuhannya menjadi image yang berjalan dengan cara yang sama di laptop, di runner CI, dan di server production. Kalau dipakai dengan benar, onboarding jadi lebih cepat dan deployment lebih bisa diprediksi. Kalau asal-asalan, hasilnya image yang sangat besar, secret yang bocor, dan container yang berjalan sebagai root.
Image dan Container dengan Bahasa Sederhana
- Image adalah paket read-only berisi aplikasi, runtime, library, dan konfigurasi default-nya. Image dibuat dari Dockerfile.
- Container adalah image yang sedang berjalan, dengan proses, jaringan, dan tampilan file system-nya sendiri.
- Registry adalah tempat menyimpan dan berbagi image, misalnya Docker Hub, GitHub Container Registry, GitLab Container Registry, atau Amazon ECR.
- Volume menyimpan data di luar container, supaya datanya tetap ada saat container diganti.
- Docker Compose mendeskripsikan beberapa container yang bekerja bersama, misalnya aplikasi, database, dan cache, dalam satu file.
Docker untuk Development Lokal
Manfaat yang paling cepat terasa adalah file Compose yang menyalakan semua dependency aplikasi. Developer baru cukup clone repository, jalankan satu perintah, dan PostgreSQL, Redis, serta penangkap email langsung berjalan dengan versi yang sama seperti di production. Banyak tim hanya menjalankan dependency di container dan tetap menjalankan aplikasinya langsung di laptop supaya reload cepat dan debugging mudah. Tim lain menjalankan semuanya di container supaya benar-benar seragam. Keduanya sama-sama bisa, asalkan versinya dikunci di file Compose dan dijelaskan di README.
Menulis Dockerfile yang Baik
- Mulai dari base image resmi yang ramping dengan versi yang dikunci, misalnya versi Node.js atau Python tertentu di Debian slim atau Alpine.
- Pakai multi-stage build: compile dan pasang build tools di tahap pertama, lalu salin hasilnya saja ke tahap runtime yang kecil.
- Salin file dependency dan install dependency dulu sebelum menyalin kode lainnya, supaya Docker bisa memakai ulang layer itu kalau yang berubah hanya kodenya.
- Tambahkan file .dockerignore supaya folder .git, node_modules, file environment lokal, dan log tidak ikut masuk ke image.
- Jalankan aplikasi sebagai user non-root, dan tulis log ke standard output supaya bisa dikumpulkan oleh platform.
- Tambahkan health check, atau endpoint health yang bisa dipanggil platform, supaya container yang bermasalah otomatis di-restart.
Multi-stage build sering memberi perbedaan paling besar. Image yang berisi compiler, dependency development, dan seluruh source code bisa beberapa kali lebih besar daripada image yang hanya berisi aplikasi hasil build dan runtime-nya. Image yang lebih kecil lebih cepat diunduh saat deployment dan berisi lebih sedikit paket yang punya celah keamanan.
Jangan Masukkan Secret ke Image
Apa pun yang disalin ke image saat build akan tetap ada di layer-nya, walaupun dihapus di langkah berikutnya, dan siapa pun yang bisa pull image itu bisa membacanya. Jangan pernah memasukkan API key, password database, atau file .env ke image. Berikan konfigurasi lewat environment variable atau secret saat container dijalankan, dan pakai build secret untuk registry package private saat build. Image yang sama sebaiknya dipakai di staging dan production, dan yang berbeda hanya konfigurasinya.
Dasar Keamanan Container
- 1Scan image untuk celah keamanan yang sudah diketahui di CI dengan tool seperti Trivy atau Docker Scout, dan gagalkan build kalau ada temuan kritis yang sudah ada perbaikannya.
- 2Build ulang image secara rutin walaupun kodenya tidak berubah, supaya update keamanan di base image ikut terbawa.
- 3Beri tag image dengan commit Git atau nomor versi, lalu deploy berdasarkan tag itu. Hindari tag latest supaya selalu jelas versi apa yang sedang berjalan.
- 4Jangan berikan akses Docker socket ke container, dan hindari mode privileged, karena keduanya memberi container kendali atas host.
- 5Batasi memori dan CPU untuk setiap container, supaya satu layanan yang bermasalah tidak menjatuhkan seluruh server.
Menjalankan Container di Production
| Pilihan | Cocok untuk | Pertimbangannya |
|---|---|---|
| Docker Compose di satu server | Aplikasi kecil dan tool internal | Mudah dijalankan, tapi kalau server mati semuanya ikut mati, dan scaling harus manual |
| Layanan container terkelola seperti Amazon ECS dengan Fargate atau Google Cloud Run | Kebanyakan aplikasi bisnis yang butuh scaling dan ketersediaan tinggi | Tidak perlu mengurus server, tapi lebih terbatas dibanding Kubernetes dan ada konfigurasi khusus platform |
| Kubernetes | Banyak layanan, beberapa tim, atau butuh portabilitas antar environment | Sangat fleksibel, tapi butuh keahlian dan usaha terus-menerus untuk mengelolanya dengan baik |
Apa pun pilihannya, simpan state di luar container. Database biasanya lebih aman di layanan managed database daripada di container di sebelah aplikasi, dan file upload sebaiknya disimpan di object storage. Dengan begitu container bisa diganti, diperbanyak, dan dipindahkan dengan bebas.
Lisensi Docker Desktop
Docker Engine dan Docker CLI bersifat open source. Docker Desktop, aplikasi yang dipakai kebanyakan developer di Windows dan macOS, gratis untuk penggunaan pribadi, pendidikan, dan bisnis kecil, tapi perusahaan yang lebih besar perlu berlangganan. Cek ketentuan terbaru sesuai ukuran perusahaan Anda. Di Windows, menjalankan Docker di dalam WSL 2, atau alternatif seperti Podman dan Rancher Desktop, juga jadi pilihan sebagian tim.
Ukur waktu onboarding sebelum dan sesudah memakai Docker: berapa lama developer baru bisa menjalankan aplikasi di laptopnya. Banyak tim turun dari satu atau dua hari menjadi kurang dari satu jam, dan angka ini cara paling mudah menunjukkan manfaatnya ke manajemen.
Poin penting
- Pakai Docker Compose supaya setiap developer punya dependency yang sama cukup dengan satu perintah.
- Tulis Dockerfile yang ramping dengan base image yang versinya dikunci, multi-stage build, .dockerignore, dan user non-root.
- Jangan masukkan secret ke image, dan berikan konfigurasi saat runtime supaya satu image bisa dipakai di semua environment.
- Scan dan build ulang image secara rutin, beri tag berdasarkan commit, dan hindari container privileged.
- Mulai production dengan Compose atau layanan container terkelola, lalu pindah ke Kubernetes kalau jumlah layanan dan tim sudah membutuhkannya.


