Model Mental Compose

Compose sebagai penerjemah YAML ke perintah Docker dan satu aplikasi sebagai satu proyek.

Daftar isi

Docker Compose adalah alat bantu yang menjalankan aplikasi multi-container dari satu berkas konfigurasi. Topik ini membangun mental model Compose terlebih dahulu: Compose membaca satu berkas compose.yaml, lalu menerjemahkan isinya menjadi sekumpulan perintah docker yang setara. Selain itu, seluruh container, jaringan, serta volume (penyimpanan yang dikelola Docker) yang lahir dari berkas itu diperlakukan sebagai satu proyek (project), yaitu kesatuan aplikasi yang dihidupkan dan dihentikan sekaligus. Pembahasan mencakup peran compose.yaml sebagai berkas konfigurasi, konsep proyek, padanan opsi docker run ke kunci YAML, serta compose.yaml pertama untuk aplikasi catatan beserta basis data PostgreSQL-nya. Setelah membacanya, deretan perintah manual dapat dinyatakan ulang sebagai satu berkas deklaratif yang pendek.

Compose sebagai penerjemah berkas konfigurasi#

Compose membaca satu berkas compose.yaml pada direktori proyek, lalu menerjemahkan setiap kuncinya menjadi argumen perintah docker yang setara. Kunci ports: berubah menjadi opsi -p, kunci environment: menjadi deretan opsi -e, dan kunci build: menjadi perintah pembangunan image dengan build context yang sesuai. Penerjemah inilah peran inti Compose, sehingga berkas tersebut tidak pernah dijalankan sendiri, melainkan dibaca Compose untuk menyusun rencana pembuatan container. Pelaksana rencana tersebut adalah daemon, yaitu proses latar yang menjalankan seluruh pekerjaan Docker.

Berkas compose.yaml ditulis dalam format YAML, yaitu format konfigurasi berbasis teks yang memakai indentasi sebagai penanda tingkat. Isinya bersifat deklaratif, artinya hanya menyatakan keadaan akhir yang diinginkan, bukan langkah-langkah untuk mencapainya. Tidak ada percabangan maupun perulangan di dalamnya, karena urutan pekerjaan ditentukan oleh Compose dan daemon, bukan oleh urutan baris berkas. Dua sifat itu membedakannya dari skrip shell yang dieksekusi baris demi baris.

compose.yaml pertama aplikasi catatan#

Contoh berikut adalah compose.yaml pertama untuk aplikasi catatan beserta basis datanya. Berkas ini diletakkan di dalam direktori proyek aplikasi-catatan, bersama Dockerfile dan app.py milik aplikasi. Dua service, yaitu deskripsi satu kelompok container pada compose.yaml, dituliskan di dalam kunci services: tingkat atas. Saat proyek dijalankan, setiap service menjadi satu container, sehingga berkas dengan dua service menghasilkan dua container yang berjalan berdampingan.

yaml compose.yaml
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgres://postgres:rahasia-db@db:5432/catatan
  db:
    image: postgres:18-alpine
    environment:
      POSTGRES_PASSWORD: rahasia-db
      POSTGRES_DB: catatan

Service web dibangun dari Dockerfile pada direktori saat ini, ditandai build: . dengan titik sebagai build context. Service db hanya menyebut image: postgres:18-alpine, sehingga image-nya ditarik dari registry, tempat penyimpanan image seperti Docker Hub, apabila image itu belum ada di mesin. Pada kunci environment:, nilai DATABASE_URL milik web memakai db sebagai nama host, yaitu nama yang diselesaikan menjadi alamat. Nilai itu berupa nama service basis data, bukan alamat IP. Nama host tersebut baru dapat diselesaikan ketika kedua container berada pada jaringan yang sama, dan pengaturannya diurus Compose sebagaimana dibahas pada topik Jaringan dan Volume dalam Compose.

Memeriksa struktur dengan pembaca YAML#

Sebelum berkas dipercaya, strukturnya dapat diperiksa dengan alat biasa karena compose.yaml pada dasarnya adalah berkas YAML biasa. Lingkungan uji modul ini tidak memiliki daemon Docker, tetapi Python dengan pustaka yaml tersedia, sehingga skrip kecil berikut cukup untuk memeriksa berkas tersebut. Skrip memuat compose.yaml, lalu mencetak setiap service beserta kunci-kuncinya.

python periksa_compose.py
# tidak-dijalankan: skrip dijalankan melalui blok bash di bawah
import yaml

with open("compose.yaml") as berkas:
    konfigurasi = yaml.safe_load(berkas)

for nama, layanan in konfigurasi["services"].items():
    kunci = ", ".join(sorted(layanan))
    print(f"service {nama}: {kunci}")
bash
# memeriksa struktur compose.yaml dengan pustaka yaml
python3 periksa_compose.py
text Keluaran
service web: build, environment, ports
service db: environment, image

Keluaran memperlihatkan dua service dengan kuncinya masing-masing. Service web memuat tiga kunci karena dibangun dari Dockerfile, sedangkan service db hanya memuat dua kunci karena cukup ditarik dari registry. Pemeriksaan semacam ini menangkap error sintaks YAML sejak dini, misalnya indentasi yang melenceng, sebelum berkas diberikan kepada Compose. Validasi kunci Compose yang lengkap tetap dilakukan Compose sendiri pada saat berkas dibaca, karena hanya Compose yang memahami aturan setiap kuncinya.

Pustaka yaml pada skrip di atas adalah PyYAML, pustaka pembaca YAML yang umum dipakai di Python, dan teknik yang sama dapat memeriksa berkas konfigurasi lain yang berformat YAML. Berkas yang indentasinya rusak membuat pemuatan berhenti dengan pesan error yang biasanya menyebut letak barisnya. Pemeriksaan awal semacam ini murah, karena hanya memerlukan Python tanpa daemon Docker sama sekali.

Proyek sebagai satu kesatuan#

Seluruh container, jaringan, dan volume yang berasal dari satu compose.yaml membentuk sebuah proyek. Nama proyek bawaan diambil dari nama direktori tempat berkas itu berada, sehingga berkas pada direktori aplikasi-catatan menghasilkan proyek bernama aplikasi-catatan. Nama ini menjadi awalan bagi sumber daya yang dibuat: container diberi nama aplikasi-catatan-web-1 dan aplikasi-catatan-db-1, dengan nomor urut di bagian akhir, sedangkan jaringan dan volume milik proyek memakai awalan yang sama.

Nama proyek membuat setiap perintah compose bekerja pada lingkup yang jelas. Perintah docker compose down yang dijalankan di dalam direktori proyek hanya menyentuh container milik proyek tersebut, bukan seluruh container di host, yaitu mesin tempat Docker berjalan. Dua salinan proyek dari berkas yang sama juga dapat berjalan berdampingan bila diberi nama proyek berbeda melalui opsi -p, misalnya satu salinan untuk pengembangan dan satu salinan untuk pengujian. Akibatnya, container yang muncul pada docker ps selalu terbaca asal proyeknya hanya dari namanya.

Satu perintah menggantikan deretan docker run#

Tanpa Compose, isi compose.yaml pertama harus diketik ulang sebagai perintah manual setiap kali aplikasi dihidupkan. Jaringan dibuat lebih dahulu, lalu setiap container dijalankan dengan opsi yang sesuai. Deretan berikut memperlihatkan bentuk manualnya.

bash
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# jaringan proyek dibuat secara manual terlebih dahulu
docker network create aplikasi-catatan_default
# container web dengan pemetaan port dan variabel lingkungannya
docker run -d --name aplikasi-catatan-web-1 --network aplikasi-catatan_default -p 8000:8000 aplikasi-catatan
# container db dengan variabel inisialisasi basis datanya
docker run -d --name aplikasi-catatan-db-1 --network aplikasi-catatan_default -e POSTGRES_PASSWORD=rahasia-db -e POSTGRES_DB=catatan postgres:18-alpine

Dengan compose.yaml, ketiga perintah itu digantikan satu perintah berikut.

bash
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# satu perintah yang dijalankan dari dalam direktori proyek
docker compose up -d

Compose membuat jaringan proyek secara otomatis, menyambungkan kedua container kepadanya, memberi nama container dari nama proyek dan nama service, lalu meneruskan seluruh kunci pada berkas sebagai konfigurasi container. Nama jaringan aplikasi-catatan_default pada deretan manual di atas memang mengikuti kebiasaan penamaan Compose, sehingga deretan manual tersebut benar-benar setara dengan hasil docker compose up -d. Tabel berikut merangkum padanan antara opsi docker run dan kunci compose.yaml yang paling sering dipakai.

Opsi pada docker runKunci pada compose.yaml
-p 8000:8000ports:
-e KUNCI=nilaienvironment:
-v catatan-data:/var/lib/postgresqlvolumes: pada service dan kunci volumes: tingkat atas
--namecontainer_name:
--restart unless-stoppedrestart:
--networknetworks:

Semua kunci pada tabel dituliskan pada tingkat service. Padanan --network jarang perlu ditulis, karena jaringan default proyek sudah dibuat dan dipasang secara otomatis. Padanan --name juga jarang dipakai, karena nama otomatis dari pola proyek-service-nomor sudah bermakna, sedangkan container_name: hanya ditulis bila sebuah nama tertentu memang dituntut alat lain.

Ringkasan#

  • Compose membaca satu berkas compose.yaml lalu menerjemahkannya menjadi sekumpulan perintah docker yang setara, dengan jaringan proyek dibuat secara otomatis.
  • Seluruh container, jaringan, dan volume dari satu compose.yaml membentuk satu proyek yang diberi nama dari nama direktorinya, sehingga setiap perintah compose bekerja pada lingkup proyek tersebut.
  • Kunci pada tingkat service memetakan opsi docker run, di antaranya ports:, environment:, volumes:, restart:, dan networks:.
  • compose.yaml adalah berkas konfigurasi deklaratif, bukan skrip, sehingga strukturnya dapat diperiksa dengan pembaca YAML biasa sebelum diberikan kepada Compose.

Referensi#