Pada Chapter sebelumnya, satu perintah docker run hello-world berhasil membuktikan bahwa Docker terpasang dan bekerja di mesin kita. Namun demo mungil itu belum menjawab pertanyaan terpenting: masalah apa sesungguhnya yang diselesaikan Docker, sampai industri perangkat lunak menjadikannya standar? Pertanyaan tersebut penting karena tanpa memahami masalahnya, seluruh fitur Docker hanya akan terasa seperti kumpulan perintah yang harus dihafal. Chapter ini membedah empat masalah nyata yang sudah puluhan tahun menyiksa tim pengembang, lalu menunjukkan bagaimana konsep image menjawabnya lewat kisah dua developer: Budi dan Siti.

Empat Masalah Klasik Pengepakan Aplikasi #

Aplikasi tidak pernah berdiri sendiri. Sebuah aplikasi web sederhana saja bergantung pada versi bahasa yang tepat, puluhan library, konfigurasi basis data, variabel lingkungan, sampai tooling di sekitarnya. Masalah mulai muncul ketika semua kebutuhan itu harus dipasang ulang secara manual di setiap mesin baru — dan empat wujud berikut adalah bentuknya yang paling sering dikeluhkan tim pengembang.

Works on My Machine #

Works on my machine adalah frasa paling legendaris dalam pengembangan perangkat lunak: aplikasi berjalan sempurna di laptop pembuatnya, lalu langsung gagal saat dijalankan di komputer orang lain atau di server. Kesalahan hampir tidak pernah ada di kodenya — yang berbeda adalah lingkungan di sekitar kode: versi runtime, library sistem, variabel lingkungan, sampai izin folder. Karena pembuat tidak bisa melihat perbedaan itu dari laptopnya sendiri, proses debug menjadi perburuan buta yang melelahkan satu tim. Yang lebih buruk, frasa ini sering diucapkan sambil melepas tanggung jawab — seolah-olah mesin milik pembuat adalah standar yang harus dituruti seluruh dunia.

Dependency Hell #

Dependency hell muncul ketika dua aplikasi yang berbagi satu mesin membutuhkan versi library yang berbeda-beda. Aplikasi lama butuh Python 3.10, proyek baru menuntut Python 3.12, sementara satu-satunya PostgreSQL yang terpasang di server adalah versi yang sudah tidak didukung aplikasi terbaru. Memperbarui satu paket untuk memenuhi kebutuhan satu aplikasi hampir selalu merusak aplikasi lain yang bergantung pada versi lamanya — menarik satu benang, simpul yang lain justru makin kusut. Tim operasional lalu terpaksa memelihara banyak server terpisah hanya untuk mengisolasi versi-versi yang saling bertabrakan, dan biaya infrastruktur membengkak seiring bertambahnya aplikasi.

Environment Drift dan Snowflake Server #

Server yang dikonfigurasi secara manual selama bertahun-tahun hampir pasti menyimpang dari dokumentasi aslinya — hotfix yang diterapkan langsung di produksi, paket yang diperbarui setengah jalan, berkas konfigurasi yang diubah tanpa dicatat. Penyimpangan bertahap semacam ini disebut environment drift, dan ujungnya adalah snowflake server: server yang begitu unik sehingga tidak ada yang berani mereproduksinya, juga tidak ada yang berani menyentuhnya. Akibatnya muncul bug aneh yang hanya terlihat di produksi tetapi tidak pernah muncul di staging, karena keduanya sudah tidak lagi identik. Ketika server macam ini akhirnya mati, tim baru sadar bahwa tidak seorang pun tahu persis bagaimana membangun penggantinya.

Konfigurasi Manual yang Tidak Terdokumentasi #

Masalah keempat adalah langkah-langkah setup yang hidup di kepala orang, bukan di dokumen. Anggota baru tim bisa menghabiskan berhari-hari menerka urutan instalasi yang bagi senior lama terasa sudah jelas; musibah kecil seperti laptop hilang atau server mati langsung menjadi krisis karena pengetahuan ikut hilang bersama pemiliknya. Dokumentasi yang sempat dibuat pun biasanya cepat kedaluwarsa karena jarang diperbarui setiap kali konfigurasi berubah. Pada akhirnya, lingkungan aplikasi yang berharga hanya bisa direkonstruksi lewat arsip riwayat obrolan dan ingatan orang-orang yang kebetulan masih ada di tim.

Studi Kasus Budi dan Siti #

Mari kita wujudkan keempat masalah itu dalam satu cerita. Budi adalah developer backend yang membangun aplikasi web katalog produk: backend Python 3.12 dengan basis data PostgreSQL. Di laptop Ubuntu 24.04 miliknya semuanya indah — virtual environment terpasang rapi, driver PostgreSQL terpasang mulus, PostgreSQL 18 berjalan sebagai service lokal, dan aplikasi menyala tanpa keluhan. Budi lalu mendorong kodenya ke repositori dan meminta Siti, rekan satu tim, untuk mencobanya.

Siti menjalankan proyek yang sama di laptop Windows 11 miliknya, dan masalah datang bergiliran. Versi Python yang terpasang adalah 3.13 — dua minor di atas milik Budi — sehingga satu dependency langsung gagal saat instalasi. Driver PostgreSQL yang harus diunduh terpisah tidak cocok dengan versi yang dibutuhkan proyek, skrip setup mengandaikan struktur folder gaya Linux, dan encoding basis data lokalnya berbeda dengan milik Budi. Dua hari kerja habis hanya untuk mengejar lingkungan yang di laptop Budi terbentuk dalam satu jam — padahal kode yang dijalankan Budi dan Siti identik, byte demi byte.

Perhatikan bahwa tidak ada pihak yang bersalah dalam cerita ini. Kode Budi benar dan laptop Siti tidak rusak; yang gagal adalah asumsi bahwa dua mesin yang berbeda akan otomatis membentuk lingkungan yang sama. Keempat masalah di atas sebenarnya hanyalah empat nama yang berbeda untuk kegagalan asumsi yang sama ini.

Image sebagai Solusi #

Image Docker membalik pendekatannya. Alih-alih memasang dependensi satu per satu di setiap mesin lalu berharap hasilnya sama, kita mengemas aplikasi bersama seluruh dependensi dan runtime-nya menjadi satu unit bernama image. Budi cukup menulis Dockerfile sekali, membangun image katalog:1.0, lalu mendorongnya ke registry. Siti menarik image yang sama persis itu dan menjalankannya sebagai container di laptop Windows-nya — Python 3.12 beserta seluruh library ikut terkemas di dalam image, dan basis data PostgreSQL yang dibutuhkan aplikasi juga tersedia sebagai image resmi yang tinggal dijalankan. Waktu setup yang tadinya dua hari kini menyusut menjadi beberapa menit, dan yang dibandingkan bukan lagi dua lingkungan berbeda, melainkan satu paket yang identik.

Alur perubahan tersebut dapat kita petakan dalam diagram berikut:

Mari kita telaah diagram di atas dari atas ke bawah:

  1. Tiga node pertama adalah masalahnya — kode aplikasi, dependensi versi tertentu, dan konfigurasi manual semuanya tersebar dan harus dirakit ulang di setiap mesin.
  2. Node belah ketupat adalah titik balik — seluruh komponen tersebut dikemas menjadi satu image, dilakukan cukup sekali lewat Dockerfile.
  3. image katalog versi 1.0 menjadi satu-satunya artefak yang berpindah — tidak ada lagi langkah instalasi manual yang harus diulang di mesin tujuan.
  4. Image yang sama persis dibawa ke laptop Budi, laptop Siti, dan server produksi — tiga mesin dengan sistem operasi berbeda tidak lagi menjadi sumber masalah.
  5. Ketiga mesin menjalankan container yang identik — frasa jalan di mesinku kehilangan artinya karena yang dibandingkan bukan lagi dua lingkungan, melainkan satu paket yang sama.

Ringkasan Masalah dan Solusi Docker #

MasalahMekanisme lamaSolusi Docker
Works on my machineAplikasi bergantung pada kondisi tak terlihat di tiap mesinSeluruh lingkungan ikut terkemas di dalam image
Dependency hellVersi library bertabrakan karena berbagi satu mesinSetiap image membawa versi dependensinya sendiri
Environment driftServer menyimpang pelan-pelan dari dokumentasiImage dibangun ulang kapan pun dari Dockerfile yang sama
Konfigurasi manual tak terdokumentasiSetup hidup di kepala orang dan riwayat obrolanDockerfile menjadi dokumentasi setup yang dapat dijalankan

Tabel di atas boleh kita jadikan ringkasan: setiap masalah lama selesai bukan karena Docker lebih pintar, melainkan karena Docker memindahkan seluruh lingkungan ke dalam satu paket yang bisa disalin. Dockerfile yang mendefinisikan image sekaligus berfungsi sebagai dokumentasi yang selalu segar — jika setup berubah, Dockerfile berubah, dan kedua hal itu tidak mungkin terpisah. Dengan begitu pengetahuan setup tidak lagi hidup di kepala orang, melainkan di repositori bersama kode aplikasinya.

Image memang menuntaskan masalah pengemasan yang telah lama menghantui tim seperti tim Budi dan Siti. Namun begitu kita memahami bahwa container berjalan tanpa sistem operasi tamu, pertanyaan berikutnya hampir selalu muncul: kalau bukan mesin virtual, apakah sebenarnya container itu, dan kapan kita tetap membutuhkan mesin virtual? Chapter Container dan Virtual Machine membandingkan keduanya aspek demi aspek.

Referensi #