Bab 26 ditutup dengan skenario yang cukup merepotkan bagi Sysadmin, yaitu menjalankan container web-test dan db-demo melalui dua perintah docker run terpisah, lalu menghubungkan keduanya secara manual melalui docker network create app-net. Cara ini masih bisa ditoleransi untuk dua container percobaan. Namun, Developer di lapangan jarang sekali membangun aplikasi hanya dari satu service. Aplikasi produksi yang realistis biasanya terdiri dari web server, database, dan tool bantu administrasi sekaligus, masing-masing dengan port, volume, dan environment variable yang berbeda. Menuliskan ulang seluruh flag docker run tersebut setiap kali server perlu dijalankan ulang bukan hanya melelahkan, melainkan juga rawan salah ketik yang berujung pada konfigurasi tidak konsisten antara satu deployment dan deployment berikutnya. Bab 27 menyelesaikan masalah ini melalui Docker Compose, yaitu tool resmi dari Docker untuk mendefinisikan seluruh aplikasi multi-container hanya dalam satu file YAML deklaratif. Bab ini dimulai dari konsep dan struktur file compose.yaml, membangun stack tiga service nyata berisi web server Nginx, database PostgreSQL 18, dan Adminer sebagai web UI administrasinya, mengelola environment variable melalui file .env, hingga menutup bab dengan restart policy dan scaling dasar agar service tetap hidup serta dapat digandakan sesuai kebutuhan beban.
27.1 Konsep Docker Compose dan Struktur File compose.yaml
Sebelum menulis file konfigurasi pertama, kita perlu memahami terlebih dahulu masalah yang sebenarnya diselesaikan oleh Docker Compose, serta tiga bagian utama yang menyusun sebuah file compose.
27.1.1 Dari Perintah docker run Berulang ke Satu File Deklaratif
Docker Compose adalah tool orkestrasi untuk lingkungan single-host yang membaca satu file YAML berisi definisi seluruh service, network, dan volume sebuah aplikasi, lalu menyamakan kondisi container yang benar-benar berjalan dengan definisi tersebut hanya melalui satu perintah. Alih-alih mengetik ulang flag -p, -v, -e, dan --network setiap kali container perlu dijalankan seperti pada Bagian 26.5.3, kita cukup menuliskannya sekali di dalam file, lalu memanggil docker compose up kapan pun dibutuhkan. Pendekatan ini disebut declarative, yaitu kita mendeskripsikan kondisi akhir yang diinginkan, bukan urutan perintah yang harus dijalankan satu per satu.
Docker Compose bukan aplikasi terpisah yang perlu dipasang sendiri di Ubuntu Server 26.04 LTS. Sejak Bagian 26.2.1, installer script resmi Docker sudah otomatis memasang paket docker-compose-plugin sebagai bagian dari instalasi Docker Engine, yang menghadirkan perintah docker compose (dua kata, tanpa tanda hubung) sebagai plugin bawaan CLI Docker. Hal ini berbeda dari docker-compose (satu kata dengan tanda hubung) generasi lama yang merupakan aplikasi Python terpisah dan sudah dinyatakan usang oleh Docker sejak Compose V2 dirilis.
Langkah Praktik
- Konfirmasikan plugin Compose sudah aktif sebagai bagian dari Docker CLI yang terpasang sejak Bab 26.
docker compose version
Verifikasi dan Troubleshooting
- Output yang sehat diawali dengan
Docker Compose version v2.x.xdiikuti hash build, menandakan plugin terbaca sebagai bagian dari Docker CLI, bukan sebagai perintah terpisah. - Jika muncul error
docker: 'compose' is not a docker command, paketdocker-compose-pluginbelum terpasang. Pasang manual melaluisudo apt install docker-compose-plugin, atau ulangi installer script resmi pada Bagian 26.2.1.
27.1.2 Anatomi compose.yaml: services, networks, dan volumes
Sebuah file compose pada dasarnya hanya tersusun dari tiga blok utama di level teratas.
services:
nama_service_1:
image: nama_image:tag
ports:
- "port_host:port_container"
nama_service_2:
image: nama_image_lain:tag
volumes:
nama_volume:Blok services adalah bagian wajib yang paling banyak diisi. Setiap key di bawahnya, misalnya nama_service_1 pada contoh di atas, menjadi satu container ketika dijalankan, lengkap dengan image, ports, volumes, environment, hingga restart policy-nya sendiri. Blok volumes di level teratas berfungsi mendeklarasikan named volume yang dikelola Docker, setara dengan perintah docker volume create yang sudah kita praktikkan secara manual pada Bagian 26.5.1, hanya saja kini cukup dideklarasikan sekali di dalam file.
Bagian ketiga, networks, justru sering tidak perlu dituliskan sama sekali. Saat docker compose up dijalankan, Compose otomatis membuatkan satu network bridge khusus untuk proyek tersebut, lalu menghubungkan seluruh service ke dalamnya tanpa perlu docker network create app-net secara manual seperti pada Bagian 26.5.3. Setiap service otomatis bisa saling menjangkau melalui nama service-nya sendiri sebagai hostname, didukung oleh embedded DNS server bawaan Docker yang sama seperti yang sudah kita bahas sebelumnya. Blok networks baru perlu dituliskan secara eksplisit jika kita membutuhkan lebih dari satu network terisolasi dalam satu aplikasi, misalnya memisahkan network frontend publik dari network backend database, sebuah pola yang akan lebih relevan saat kita membahas hardening jaringan pada Bagian VIII nanti.
Ada dua catatan penting soal penamaan sebelum kita mulai menulis file sungguhan. Pertama, field version yang dulu wajib dituliskan di baris paling atas file (misalnya version: "3.8") kini sudah usang sejak Docker mengadopsi penuh Compose Specification. Field ini boleh dihilangkan sepenuhnya karena Compose modern selalu memvalidasi file memakai skema terbaru, apa pun nilai version yang dituliskan. Kedua, mengenai nama file itu sendiri: Compose CLI mencari compose.yaml terlebih dahulu sebagai nama baku yang direkomendasikan, baru kemudian compose.yml, docker-compose.yaml, dan docker-compose.yml sebagai nama lama untuk kompatibilitas ke belakang. Series ini memakai compose.yaml sebagai nama file di seluruh contoh praktik, tetapi docker-compose.yml yang mungkin lebih akrab di banyak tutorial lama tetap didukung penuh dan bekerja secara identik.
27.2 Menjalankan Aplikasi Multi-Service: Web, Database, dan Adminer
Bagian ini mempraktikkan langsung sebuah stack tiga service: web server Nginx, database PostgreSQL 18 seperti yang sudah dibahas di Bab 18, dan Adminer sebagai web UI administrasi database bergaya container, sebagai pembanding dari pgAdmin 4 yang dipasang secara native di Bab 22.
27.2.1 Menyiapkan Struktur Proyek
Langkah Praktik
- Buat direktori proyek beserta folder konten web statis.
mkdir -p ~/app-compose/html cd ~/app-compose - Buat halaman HTML sederhana sebagai konten web.
echo "<h1>Aplikasi contoh berjalan lewat Docker Compose</h1>" > html/index.html
27.2.2 Menulis compose.yaml Lengkap untuk Tiga Service
Langkah Praktik
- Buat file
.envberisi nilai kredensial database dan port yang akan dipakai. Detail lengkap mengenai file ini dibahas pada Bagian 27.3; untuk sekarang cukup pahami bahwa file ini menampung nilai yang tidak ditulis langsung dicompose.yaml.nano .envPOSTGRES_USER=notes_user POSTGRES_PASSWORD=ganti_password_ini POSTGRES_DB=notes_db WEB_PORT=8090 ADMINER_PORT=8091 - Buat
compose.yamldi direktori yang sama.nano compose.yaml
Berikut adalah beberapa bagian penting untuk dipahami. Serviceservices: web: image: nginx:stable restart: unless-stopped ports: - "${WEB_PORT}:80" volumes: - ./html:/usr/share/nginx/html:ro db: image: postgres:18 restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U notes_user -d notes_db"] interval: 5s timeout: 5s retries: 5 adminer: image: adminer restart: unless-stopped ports: - "${ADMINER_PORT}:8080" depends_on: db: condition: service_healthy volumes: db-data:webmemakaivolumesdengan bentuk bind mount seperti pada Bagian 26.5.2, memetakan folder./htmldi host ke document root Nginx, dengan akhiran:ro(read-only) agar container tidak bisa menulis balik ke folder host. Servicedbmemakaihealthcheckberbasispg_isready, yaitu utility bawaan PostgreSQL untuk memeriksa apakah server database sudah benar-benar siap menerima koneksi, bukan sekadar prosespostgresyang sudah menyala. Serviceadminermemakaidepends_ondengancondition: service_healthy, artinya container Adminer baru benar-benar dijalankan setelahhealthcheckmilikdbmelaporkan status sehat, bukan sekadar menunggu containerdbberstatus "running" yang bisa saja tercapai sebelum PostgreSQL selesai diinisialisasi.
27.2.3 Menjalankan Stack dengan docker compose up
Langkah Praktik
- Jalankan seluruh stack di latar belakang dari direktori proyek.
Compose membuat satu network bridge baru bernamadocker compose up -dapp-compose_default(mengikuti nama direktori proyek sebagai project name), volumeapp-compose_db-data, lalu menjalankan ketiga container secara berurutan sesuai dependensi:dblebih dulu, disusulwebyang tidak memiliki dependensi, danadminerpaling akhir setelahdbberstatus sehat. Perhatikan bahwa container-nya sendiri dinamai dengan tanda hubung, misalnyaapp-compose-db-1, berbeda dari network dan volume yang memakai underscore seperti di atas. Bukan salah ketik, melainkan memang konvensi penamaan resource yang berbeda di internal Compose: container mengikuti formatproject-service-index, sedangkan network dan volume mengikuti formatproject_nama.
Verifikasi dan Troubleshooting
- Lihat status ketiga container sekaligus, termasuk kolom health check.
docker compose ps - Akses halaman web statis yang baru saja berjalan.
Output seharusnya menampilkan bariscurl http://localhost:8090<h1>Aplikasi contoh berjalan lewat Docker Compose</h1>yang telah kita buat pada Bagian 27.2.1. - Buka
http://alamat-ip-server:8091dari browser untuk login ke Adminer. Isi form login dengan SystemPostgreSQL, Serverdb(nama service, bukanlocalhostatau IP address, karena keduanya terhubung melalui embedded DNS pada network Compose yang sama), Usernamenotes_user, Password sesuai isi.env, dan Databasenotes_db. Login yang berhasil akan menampilkan halaman administrasi Adminer dengan databasenotes_dbyang masih kosong. - Jika port 8090 atau 8091 sudah dipakai proses lain, ganti nilainya di
.envlalu jalankan ulangdocker compose up -d. Jika UFW sudah aktif seperti yang nanti dibahas pada Bab 31, pastikan kedua port tersebut diizinkan terlebih dahulu sebelum diakses dari komputer lain. - Jika
adminerpadadocker compose pstampak lama di kolomSTATUStanpa kunjung menjadiStarted, periksa terlebih dahulu apakahdbsudah healthy.
Baris logdocker compose logs dbdatabase system is ready to accept connectionsmenandakan PostgreSQL sudah benar-benar siap. Jika baris ini belum muncul, healthcheck memang akan terus menahanadmineragar tidak dijalankan lebih dahulu, sesuai dengan desaindepends_onpada Bagian 27.2.2.
27.2.4 Perintah Operasional Sehari-hari
Beberapa perintah berikut akan sering dipakai Sysadmin setelah stack berjalan, jauh lebih ringkas dibanding mengelola tiap container satu per satu seperti pada Bab 26.
| Perintah | Fungsi |
|---|---|
docker compose ps | Melihat status seluruh service dalam project |
docker compose logs -f nama_service | Mengikuti log satu service tertentu secara real-time |
docker compose stop | Menghentikan seluruh container tanpa menghapusnya |
docker compose start | Menjalankan kembali container yang sudah dihentikan stop |
docker compose restart nama_service | Me-restart satu service tanpa mengganggu service lain |
docker compose down | Menghentikan lalu menghapus container dan network, volume tetap aman |
docker compose down -v | Sama seperti di atas, tetapi ikut menghapus volume secara permanen |
Verifikasi dan Troubleshooting
- Ikuti log service
dbsecara langsung, berguna saat debugging query atau koneksi yang gagal dari Adminer.
Tekandocker compose logs -f dbCtrl+Cuntuk keluar dari mode follow tanpa menghentikan container itu sendiri. - Catatan jujur mengenai risiko: flag
-vpadadocker compose down -vmenghapus volumedb-datasecara permanen beserta seluruh isi database di dalamnya. Jangan pernah menjalankan perintah ini di server produksi tanpa backup terlebih dahulu, mengikuti prinsip yang sama seperti strategi backup database pada Bab 23.
27.3 Environment Variable dan File .env
Bagian ini membedah dua cara berbeda Compose memanfaatkan file .env, sebuah perbedaan yang sering membingungkan karena keduanya sama-sama memakai file dengan nama yang sama, tetapi bekerja pada tahap yang sepenuhnya berbeda.
27.3.1 Interpolasi Nilai dari .env ke compose.yaml
Compose secara otomatis membaca file .env yang berada satu direktori dengan compose.yaml, lalu mengganti setiap penanda ${NAMA_VARIABLE} di dalam file itu dengan nilai aslinya. Proses ini disebut interpolation, dan terjadi murni di level Compose CLI saat file sedang dibaca, jauh sebelum satu pun container benar-benar dibuat. Pola inilah yang sudah kita pakai pada ${WEB_PORT}, ${ADMINER_PORT}, dan tiga variable PostgreSQL pada Bagian 27.2.2.
Langkah Praktik
- Lihat hasil akhir
compose.yamlsetelah seluruh proses interpolasi selesai, tanpa benar-benar menjalankan apa pun.docker compose config
Verifikasi dan Troubleshooting
- Output
docker compose configmenampilkan file YAML lengkap dengan setiap${...}sudah tergantikan nilai aslinya, termasuk password database dalam bentuk plaintext apa adanya. Perintah ini sangat berguna untuk debugging saat sebuah variable tidak terbaca sesuai harapan, karena kita bisa langsung melihat nilai final yang benar-benar dikirim ke Docker Engine. - Jika sebuah
${VARIABLE}muncul kosong di outputdocker compose config, kemungkinan besar nama variable di.envsalah ketik, atau perintah dijalankan dari direktori yang berbeda dari lokasi file.envitu sendiri, karena Compose hanya mencarinya di direktori kerja saat ini.
27.3.2 env_file untuk Mengirim Variable Langsung ke Container
Cara kedua memiliki tujuan yang berbeda sepenuhnya. Alih-alih menyisipkan nilai ke dalam compose.yaml melalui interpolasi, directive env_file mengirimkan seluruh baris di dalam sebuah file langsung menjadi environment variable di dalam proses container, persis seperti flag -e pada docker run. Karena tiga variable POSTGRES_USER, POSTGRES_PASSWORD, dan POSTGRES_DB di .env kita kebetulan sudah memakai nama persis yang dikenali image resmi postgres, blok environment pada service db sebenarnya bisa disederhanakan.
Langkah Praktik
- Ubah service
dbdicompose.yaml, ganti blokenvironmentdenganenv_file.db: image: postgres:18 restart: unless-stopped env_file: .env volumes: - db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U notes_user -d notes_db"] interval: 5s timeout: 5s retries: 5 - Terapkan perubahan. Compose otomatis mendeteksi hanya definisi
dbyang berubah, sehingga hanya container tersebut yang dibuat ulang, sementarawebdanadminertidak ikut terganggu.docker compose up -d
Verifikasi dan Troubleshooting
- Periksa environment variable yang benar-benar diterima container
db.
Ketiga variable seharusnya tetap muncul dengan nilai yang sama seperti sebelumnya, meskipun sekarang dikirim melaluidocker compose exec db env | grep POSTGRESenv_file, bukan melalui interpolasi${...}. - Catatan dari lapangan:
env_filemengirim seluruh baris di dalam file, termasukWEB_PORTdanADMINER_PORTyang sebenarnya sama sekali tidak relevan untuk container database. Hal ini sedikit mengotori environment container dibanding pendekatanenvironmenteksplisit pada Bagian 27.2.2, yang hanya mengirim variable yang benar-benar dibutuhkan. Untuk aplikasi dengan banyak variable sensitif dan tidak sensitif tercampur, pertimbangkan memisahkan konfigurasi menjadi beberapa file.envkhusus per service. - Jika kedua directive
environmentdanenv_filedipakai bersamaan pada satu service dengan nama variable yang sama, nilai darienvironmentselalu diprioritaskan, sesuai urutan prioritas resmi Compose.
27.3.3 Mengamankan .env agar Tidak Ikut ke Git
File .env menyimpan password dalam bentuk plaintext, sehingga perlu diperlakukan sama hati-hatinya seperti file kredensial lain yang sudah kita jaga sepanjang series ini.
Langkah Praktik
- Batasi permission file
.envagar hanya bisa dibaca oleh pemiliknya sendiri.chmod 600 .env - Jika direktori proyek ini nantinya dikelola melalui Git, pastikan
.envtidak pernah ikut ter-commit.echo ".env" >> .gitignore - Sebagai gantinya, buat file
.env.exampleberisi nama variable tanpa nilai asli, sebagai dokumentasi untuk Developer lain di tim yang perlu mengetahui variable apa saja yang dibutuhkan, tanpa membocorkan kredensial sungguhan.
Filecat > .env.example << 'EOF' POSTGRES_USER= POSTGRES_PASSWORD= POSTGRES_DB= WEB_PORT= ADMINER_PORT= EOF.env.exampleinilah yang aman untuk ikut di-commit ke Git, sementara file.envasli tetap tersimpan secara lokal di server masing-masing.
Verifikasi dan Troubleshooting
- Catatan jujur mengenai keamanan: baik
.env,environment, maupunenv_file, ketiganya tetap menyimpan dan mengirim nilai dalam bentuk plaintext, yang terlihat jelas melaluidocker compose configmaupundocker inspectoleh siapa pun yang memiliki akses shell ke server. Untuk kebutuhan produksi yang benar-benar sensitif, seperti API key pihak ketiga atau password database produksi, pertimbangkan mekanisme secret management yang lebih matang, misalnya Docker secrets pada Docker Swarm atau tool eksternal seperti HashiCorp Vault, yang berada di luar cakupan bab ini.
27.4 Restart Policy dan Startup Order yang Aman
Server produksi cepat atau lambat akan mengalami restart, baik secara terjadwal maupun tidak terduga. Bagian ini memastikan ketiga service kita bangkit kembali secara otomatis dan dalam urutan yang benar setiap kali hal itu terjadi.
27.4.1 Empat Pilihan restart Policy
Directive restart pada level service menentukan perilaku Docker Engine ketika sebuah container berhenti, baik karena crash maupun alasan lain.
| Nilai | Perilaku |
|---|---|
no | Default bawaan Docker. Container tidak pernah di-restart otomatis dalam kondisi apa pun |
always | Selalu di-restart, termasuk setelah dihentikan manual lewat docker stop, sampai container benar-benar dihapus |
on-failure[:max-retries] | Hanya di-restart jika exit code menandakan error, dengan batas jumlah percobaan opsional |
unless-stopped | Selalu di-restart apa pun exit code-nya, kecuali container memang dihentikan secara sengaja lewat stop |
Ketiga service kita pada Bagian 27.2.2 memakai unless-stopped, yaitu pilihan yang paling umum untuk service jangka panjang seperti web server dan database. Kebijakan ini memastikan container ikut menyala lagi setelah dockerd atau bahkan seluruh host di-reboot, tetapi tetap menghormati keputusan Sysadmin ketika sebuah service memang sengaja dihentikan melalui docker compose stop untuk keperluan maintenance.
Langkah Praktik
- Simulasikan container
dbyang crash mendadak dengan mengirim sinyal paksa.docker kill app-compose-db-1 - Tunggu beberapa detik, lalu periksa statusnya kembali.
docker compose ps - Sebagai pembanding, hentikan
dbsecara resmi melalui Compose, bukan melaluikill.docker compose stop db
Verifikasi dan Troubleshooting
- Setelah langkah 2,
dbseharusnya kembali berstatusrunningtanpa perlu perintahdocker compose upapa pun, karenadockerdsendiri yang memantau dan menerapkanrestartpolicy begitu mendeteksi container berhenti secara tak terduga. - Setelah
docker compose stop dbpada langkah 3, jalankan lagidocker compose ps: kali inidbtetap berstatus berhenti dan tidak otomatis bangkit lagi, karenaunless-stoppedsecara sengaja mengecualikan penghentian manual dari mekanisme restart otomatis. Nyalakan kembali melaluidocker compose start db. - Catatan penting yang sering salah dipahami: baik
alwaysmaupununless-stoppedsama sekali tidak mencegahdocker compose downmenghapus container. Kedua restart policy ini hanya mengatur perilaku setelah crash atau reboot host, bukan melindungi container dari perintah penghapusan eksplisit.
27.4.2 Startup Order Aman dengan Health Check dan depends_on
Bagian ini sebenarnya sudah kita praktikkan sejak Bagian 27.2.2 melalui kombinasi healthcheck pada db dan depends_on: condition: service_healthy pada adminer. Tanpa kombinasi ini, depends_on versi sederhana hanya menjamin urutan container dibuat, bukan urutan aplikasi di dalamnya benar-benar siap. Hal ini merupakan sebuah jebakan klasik yang membuat service dependent kadang gagal terhubung pada percobaan pertama karena database masih dalam proses inisialisasi.
Langkah Praktik
- Hapus seluruh stack lalu jalankan ulang dari kondisi bersih untuk mengamati urutan startup secara langsung.
docker compose down docker compose up -d - Segera setelah perintah di atas selesai, periksa status kesehatan
dbsecara mentah.docker inspect --format='{{json .State.Health.Status}}' app-compose-db-1
Verifikasi dan Troubleshooting
- Nilai yang dikembalikan berubah dari
"starting"menjadi"healthy"dalam beberapa detik, sesuai dengan parameterintervaldanretriesyang telah ditentukan pada Bagian 27.2.2. Containeradminerbaru benar-benar masuk statusrunningsetelah nilai ini menjadi"healthy". - Untuk aplikasi dengan waktu startup yang jauh lebih lama dari PostgreSQL, misalnya aplikasi Java yang membutuhkan waktu puluhan detik untuk warm-up, tambahkan parameter
start_periodpadahealthcheckagar kegagalan check di awal proses booting tidak langsung dihitung sebagai kegagalan sungguhan.
27.5 Scaling Dasar dengan docker compose up --scale
Bagian penutup ini mempraktikkan cara menjalankan banyak instance dari satu service sekaligus, yang merupakan kebutuhan umum ketika satu container Nginx saja tidak lagi cukup untuk menampung traffic.
27.5.1 Menjalankan Banyak Instance Service Sekaligus
Langkah Praktik
- Coba gandakan service
webmenjadi tiga instance memakai konfigurasicompose.yamlyang masih apa adanya dari Bagian 27.2.2.
Perintah ini gagal dengan error serupadocker compose up -d --scale web=3Bind for 0.0.0.0:8090 failed: port is already allocated. Penyebabnya adalah ketiga instance sama-sama mencoba mengikat port host8090yang sama persis melaluiports: "${WEB_PORT}:80", padahal satu port host hanya bisa dipakai oleh satu proses. - Ubah bagian
portspada servicewebdicompose.yaml, hilangkan sisi port host dan sisakan port container saja.
Melalui penulisan port container saja, Docker Engine memilih port host secara otomatis dari ephemeral port range milik kernel (umumnya di rentang 32768 sampai 60999 pada Linux) untuk setiap instance, sehingga tidak ada lagi tabrakan port antar-replika.web: image: nginx:stable restart: unless-stopped ports: - "80" volumes: - ./html:/usr/share/nginx/html:ro - Ulangi scaling setelah perubahan diterapkan.
docker compose up -d --scale web=3
Verifikasi dan Troubleshooting
- Lihat port host acak yang didapat masing-masing instance.
Kolomdocker compose psPORTSmenampilkan tiga bariswebdengan port host yang berbeda-beda satu sama lain. - Ambil port spesifik salah satu replika secara terprogram, berguna untuk skenario otomasi atau script monitoring.
Perintah pertama mengembalikan port milik replika pertama (index 0, default jikadocker compose port web 80 docker compose port --index 2 web 80--indextidak dituliskan), sedangkan perintah kedua mengembalikan port milik replika ketiga. - Akses salah satu replika melalui port yang baru saja didapat, misalnya jika hasilnya
32771.curl http://localhost:32771
27.5.2 Keterbatasan Load Balancing Bawaan Compose
Scaling melalui docker compose up --scale murni menggandakan jumlah container yang berjalan, tanpa menyediakan satu titik akses tunggal yang otomatis membagi traffic ke seluruh replika. Klien harus tahu persis port mana yang hendak dituju, seperti yang baru saja kita praktikkan melalui docker compose port. Hal ini jelas belum cukup untuk skenario produksi sungguhan, ketika Visitor cukup mengakses satu domain atau IP saja tanpa perlu tahu ada berapa banyak replika di baliknya.
Solusi yang paling umum di lapangan adalah menambahkan satu load balancer di depan seluruh replika ini, misalnya melalui konsep upstream Nginx yang sudah kita bahas pada Bagian 16.2, dengan setiap port acak hasil scaling didaftarkan sebagai salah satu backend. Namun, pendekatan ini tetap merepotkan karena port acak berubah setiap kali stack dijalankan ulang. Untuk kebutuhan scaling otomatis dengan service discovery bawaan, tanpa perlu mendaftarkan port secara manual satu per satu, orchestrator khusus seperti Docker Swarm atau Kubernetes jauh lebih tepat dibanding Docker Compose murni. Catatan jujur yang perlu dipahami sejak awal adalah bahwa Docker Compose dirancang untuk lingkungan single-host, seperti development, testing, atau aplikasi skala kecil hingga menengah, bukan sebagai pengganti orchestrator produksi skala besar.
Langkah Praktik
- Bersihkan seluruh stack sebelum melanjutkan ke Bab 28, termasuk volume database agar tidak menumpuk data percobaan.
docker compose down -v
Verifikasi dan Troubleshooting
- Konfirmasikan tidak ada lagi container maupun volume tersisa dari proyek ini.
Kedua perintah seharusnya tidak menampilkan hasil apa pun terkait proyekdocker compose ps -a docker volume ls | grep app-composeapp-compose.
Sampai di sini, kita sudah bisa mendefinisikan aplikasi multi-container lengkap dalam satu file compose.yaml, mengelola kredensial melalui .env dengan aman, memastikan service bangkit kembali otomatis melalui restart policy yang tepat, serta menggandakan service melalui scaling dasar. Docker dan Docker Compose menyelesaikan masalah packaging dan orkestrasi container di satu host, tetapi container tetap berbagi kernel yang sama dengan host-nya seperti yang dibahas pada Bagian 26.1. Bab 28 beralih ke pendekatan isolasi yang sepenuhnya berbeda melalui virtualisasi penuh menggunakan KVM dan QEMU, di mana setiap virtual machine benar-benar menjalankan kernelnya sendiri, cocok untuk kebutuhan yang menuntut isolasi keamanan lebih ketat atau menjalankan sistem operasi yang berbeda dari host.

