Compose melakukan pengkabelan aplikasi multi-container secara deklaratif, yaitu tanpa perintah yang diketik manual. Jaringan milik proyek (project), yaitu kesatuan container dari satu compose.yaml, dibuat otomatis untuk seluruh service, yaitu deskripsi satu kelompok container pada berkas. Volume bernama, yaitu penyimpanan yang dikelola Docker, dideklarasikan sekali pada berkas, sedangkan bind mount memasang direktori host, mesin tempat Docker berjalan, ke dalam container, cukup dengan satu baris. Topik ini membahas ketiga mekanisme tersebut pada compose.yaml aplikasi catatan, beserta penamaan asli sumber dayanya dan isolasi antar proyek. Setelah membacanya, web dan basis data terhubung lewat nama service, dan penyimpanan datanya terpasang pada tempat yang benar.
Jaringan proyek yang dibuat otomatis#
Saat proyek dihidupkan, Compose membuat satu jaringan bernama <proyek>_default dan menyambungkan seluruh service kepadanya tanpa satu pun deklarasi pada berkas. Untuk proyek aplikasi-catatan, jaringan itu bernama aplikasi-catatan_default. Jaringan ini adalah jaringan kustom milik proyek, sehingga dilengkapi server DNS tertanam yang menerjemahkan nama menjadi alamat container, sebagaimana jaringan kustom pada umumnya. Karena itulah nilai DATABASE_URL pada service web memakai db sebagai nama host, dan nama itu diselesaikan menjadi alamat container db tanpa konfigurasi tambahan.
Diagram berikut merangkum pengkabelan satu proyek: dua service berada pada satu jaringan default, web memasang direktori proyek sebagai bind mount, sedangkan db memasang volume bernama.
Pemetaan port tidak ikut dibuat otomatis. Kunci ports: "8000:8000" tetap ditulis pada service web agar aplikasi dapat dijangkau dari host. Service db sengaja tidak memetakan port apa pun, sehingga basis data hanya dapat dijangkau oleh container lain di dalam jaringan proyek. Pembatasan ini mengikuti prinsip publishing versus exposing: port yang dipublikasikan terbuka dari luar, sedangkan service tanpa pemetaan port tetap dapat dihubungi sesama container.
Volume bernama pada kunci volumes tingkat atas#
Volume bernama dideklarasikan pada kunci volumes: tingkat atas, lalu dirujuk oleh service yang membutuhkannya. Deklarasi tingkat atas hanya berisi nama dan definisi kosong, sedangkan service menuliskan pasangan nama dan jalur pemasangannya. Daftar pada tingkat atas menjadi inventaris milik proyek, sehingga sumber daya penyimpanan yang akan tercipta terbaca langsung dari bagian bawah berkas. Berkas compose.yaml lengkap untuk topik ini menjadi seperti berikut.
services:
web:
build: .
ports:
- "8000:8000"
environment:
DATABASE_URL: postgres://postgres:rahasia-db@db:5432/catatan
volumes:
- .:/aplikasi
db:
image: postgres:18-alpine
environment:
POSTGRES_PASSWORD: rahasia-db
POSTGRES_DB: catatan
volumes:
- catatan-data:/var/lib/postgresql
volumes:
catatan-data:Volume catatan-data dimiliki proyek, sehingga namanya di host diberi awalan proyek menjadi aplikasi-catatan_catatan-data. Awalan ini terlihat pada docker volume ls setelah proyek dihidupkan, dan aturan yang sama berlaku untuk jaringan. Volume proyek dibuat saat up bila belum ada, bertahan setelah down, dan hanya dihapus bersama seluruh datanya oleh down -v. Jalur pemasangan /var/lib/postgresql mengikuti deklarasi penyimpanan image postgres:18-alpine sebagaimana dibahas pada topik Volume Bernama. Pendekatan dua tingkat ini menjaga keduanya tetap terpisah, karena service tidak perlu tahu bagaimana volume diciptakan, sedangkan daftar tingkat atas tidak perlu tahu jalur pemasangannya.
Bind mount untuk alur pengembangan#
Baris - .:/aplikasi pada service web adalah bind mount, yaitu pemasangan direktori host ke jalur tertentu di dalam container dengan sintaks pendek sumber:tujuan. Titik berarti direktori proyek saat ini, sedangkan /aplikasi adalah direktori kerja pada Dockerfile aplikasi catatan. Dengan pemasangan ini, setiap perubahan app.py di host langsung terlihat oleh container tanpa membangun ulang image, sehingga siklus sunting dan coba berlangsung cepat selama pengembangan.
Bind mount dan volume bernama memang sama-sama ditulis pada kunci volumes:, tetapi keduanya melayani kebutuhan yang berbeda. Tabel berikut menyandingkannya.
| Aspek | Bind mount .:/aplikasi | Volume bernama catatan-data |
|---|---|---|
| Sumber | Direktori host yang dipilih sendiri | Penyimpanan yang dikelola Docker |
| Isi | Kode sumber yang disunting terus | Berkas basis data yang harus bertahan |
| Cocok untuk | Alur pengembangan aplikasi | Penyimpanan data yang melampaui umur container |
Volume bernama tetap menjadi pilihan untuk data basis data karena isinya dikelola Docker dan tidak bergantung pada struktur direktori kerja. Bind mount sebaliknya menempelkan keadaan direktori host apa adanya, sehingga cocok untuk berkas yang memang disunting dari luar container.
Isolasi antar proyek#
Nama service hanya berlaku di dalam jaringan proyeknya, dan inilah sumber isolasi antar proyek. Dua salinan proyek yang dihidupkan dengan nama proyek berbeda mendapat jaringan default yang berbeda pula. Karena itu, service web milik proyek yang satu tidak pernah menjangkau db milik proyek yang lain, meskipun kedua proyek dibangun dari berkas yang sama persis. Isolasi ini berlaku dua arah karena setiap jaringan hanya mengenal anggotanya sendiri, dan server DNS yang tertanam hanya memuat daftar nama jaringannya masing-masing.
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# salinan proyek kedua dengan nama proyek berbeda
docker compose -p aplikasi-catatan-uji up -d
# jaringan dan volume milik proyek terlihat pada daftar milik Docker
docker network ls
docker volume lsPerintah docker network ls pada keadaan itu menampilkan dua jaringan, yaitu aplikasi-catatan_default dan aplikasi-catatan-uji_default, sedangkan docker volume ls menampilkan dua volume dengan awalan proyek masing-masing. Kedua kelompok container hidup berdampingan tanpa bentrok nama, karena setiap nama container diberi awalan nama proyeknya dan setiap nama service hanya dijawab DNS di dalam jaringannya sendiri. Isolasi ini memungkinkan pengujian versi baru aplikasi di samping versi yang sedang berjalan, tanpa satu pun perubahan pada berkasnya.
Kesalahan umum#
Menghubungi basis data dengan
localhost. Dari dalam container web,localhostmenunjuk container web itu sendiri, sehingga koneksi ke basis data selalu gagal meskipun container db berjalan normal. Perbaikannya dengan memakai nama servicedbsebagai nama host padaDATABASE_URL.Merujuk volume tanpa mendeklarasikannya. Baris
catatan-data:/var/lib/postgresqlpada service ditolak Compose dengan error volume yang tidak terdefinisi bila kuncivolumes:tingkat atas tidak memuatcatatan-data. Perbaikannya dengan mendeklarasikan nama volume tersebut pada kunci tingkat atas.Memasang bind mount pada direktori host yang kosong. Isi direktori host menimpa isi image pada jalur yang dipasang, sehingga direktori kosong membuat
app.pytidak terlihat oleh container dan aplikasi berhenti segera setelah mulai. Perbaikannya dengan memastikan direktori host memuat kode, atau memasang bind mount hanya ke jalur yang memang dituju.
Ringkasan#
- Compose membuat satu jaringan
<proyek>_defaultdan menyambungkan seluruh service kepadanya, sehingga service saling dijangkau melalui nama service-nya. - Volume bernama dideklarasikan pada kunci
volumes:tingkat atas lalu dirujuk service, dan nama aslinya di host diberi awalan nama proyek. - Bind mount ditulis dengan sintaks pendek
sumber:tujuan, misalnya.:/aplikasi, dan mempercepat alur pengembangan tanpa membangun ulang image. - Nama service hanya berlaku dalam jaringan proyeknya, sehingga dua proyek dengan nama service sama tetap saling terisolasi.
Referensi#
- Services — Docker Docs
— Rujukan kunci
volumes:danports:pada tingkat service. - Compose file reference — Docker Docs
— Rujukan kunci
volumes:dannetworks:tingkat atas pada compose.yaml.