Bab penutup test kita meninggalkan satu pertanyaan terbuka: bagaimana caranya laptop Budi, laptop Siti, dan mesin CI menjalankan kombinasi yang berbeda dari perangkat yang sama tanpa saling menginjak? Di dunia nyata jawabannya jarang berupa satu berkas untuk semua. Setiap developer membawa preferensi sendiri — port yang tidak bentrok dengan aplikasi lain, profil debug yang hanya aktif saat dipakai, database uji yang boleh dibuang kapan saja — sementara tim membutuhkan satu kontrak bersama yang bisa dibaca siapa pun yang baru bergabung. Chapter penutup Section ini merapikan seluruh kombinasi itu menjadi peta environment yang bisa dipelihara: profile untuk fitur opsional, berkas lokal untuk selera personal, dan ritual kebersihan resource agar laptop tidak perlahan tenggelam oleh sisa-sisa eksperimen.

Peta tiga environment sehari-hari #

Sebelum mengatur perangkatnya, mari sepakati dulu bentuk medannya. Tiga environment inilah yang paling sering hidup bersamaan di mesin seorang developer:

EnvironmentBerkas ComposeDataPort khasPenghuni
Dev personalcompose.yaml + compose.override.yaml (otomatis)volume lokal, boleh dibuang8080 atau WEB_PORT milik sendirisatu orang, semua service
Dev timcompose.yaml + compose.local.yaml (eksplisit)volume lokal per mesinWEB_PORT per orang lewat .envtiap anggota menyalin template
Stagingcompose.yaml + compose.staging.yaml (eksplisit)volume khusus st_ atau project terpisah8080 tetap, host berbedasatu mesin bersama

Perbedaan paling penting ada pada kolom kedua: environment personal memakai berkas override yang dimuat otomatis, sedangkan environment tim dan staging memakai berkas eksplisit yang sengaja dipilih lewat flag -f. Aturan pemisahan ini bukan gaya-gayaan — konsekuensinya nyata pada perintah yang dijalankan setiap orang.

Override otomatis versus berkas lokal eksplisit #

Aturan pertama sudah kita kenal dari chapter Compose Override dan Environment: compose.override.yaml dimuat otomatis selama berkas itu ada di sebelah compose.yaml. Sifat itu ideal untuk personalisasi yang tidak boleh bocor ke rekan — misalnya command: npm run dev beserta blok develop.watch. Sebaliknya, berkas bernama lain seperti compose.local.yaml tidak pernah dimuat sendiri; ia hanya hidup bila disebut eksplisit:

bash
docker compose -f compose.yaml -f compose.local.yaml up -d

Dua konsekuensi penting mengikuti pemakaian -f:

  1. Penyebutan eksplisit mematikan auto-discovery. Begitu flag -f muncul, Compose berhenti mencari compose.override.yaml — berkas override otomatis diabaikan sepenuhnya. Karena itu pilih jalur yang satu per kebutuhan: jangan mencampur keduanya dalam satu perintah.
  2. Merge tetap berjalan per kunci. Aturan penggabungan yang kita pelajari — map digabung dalam, sequence umum diganti total, ports dan volumes digabung — berlaku sama persis antara berkas eksplisit. Yang berubah hanyalah siapa yang memuatnya.

Berkas lokal yang tidak dimaksudkan untuk dibagikan sudah selayaknya masuk .gitignore — pola yang sama dengan .env:

text
compose.local.yaml
.env

Sementara itu, berkas yang memang dibaca seluruh tim — compose.yaml, compose.staging.yaml, .env.example — tetap di-commit agar onboarding rekan baru selesai dalam satu git clone.

.env per orang, .env.example di repo #

Setiap mesin punya nasib portnya sendiri. Laptop Siti memegang 8080 untuk aplikasi internal; Budi harus menerima 8082. Variabel per orang inilah pekerjaan berkas .env, yang dibaca Compose untuk interpolasi — mekanisme lengkapnya ada di chapter Variable Interpolation:

bash
# .env — milik Budi, tidak di-commit
WEB_PORT=8082
IMAGE_TAG=dev
COMPOSE_PROFILES=debug

Tiga baris itu mengerjakan tiga pekerjaan berbeda sekaligus. WEB_PORT mengalir ke pemetaan port di compose.yaml (${WEB_PORT:-8080}:80) sehingga Budi dan Siti berbagi satu berkas tanpa bertengkar. IMAGE_TAG menentukan tag image yang ditarik (${IMAGE_TAG:-dev}), berguna saat Budi menguji rilis kandidat sebelum di-deploy. COMPOSE_PROFILES=debug mengaktifkan service berprofil debug — container alat diagnostik dari chapter Profiles — tanpa perlu mengetik --profile debug setiap kali.

Satu CLI, tiga project #

Dengan peta di atas, docker compose ls menjadi papan kendali yang jujur — perintah ini melihat project dari sudut pandang daemon, bukan folder:

bash
docker compose ls

Output yang Dihasilkan:

text
NAME                STATUS          CONFIG FILES
katalog             running(4)      /home/budi/katalog/compose.yaml
katalog-staging     running(4)      /srv/staging/compose.yaml
katalog-uji         exited(2)       /home/budi/katalog/compose.yaml

Tiga project itu hidup dari berkas yang hampir sama namun tidak saling mengganggu — nama project menjadi ruang nama bagi container, jaringan, dan volumenya. Ada dua batas praktis yang perlu dihormati: konflik port host tetap terjadi bila dua project memetakan port statis yang sama (kembali ke WEB_PORT), dan RAM laptop dibagi oleh semua yang berjalan bersamaan. Batas kedua inilah yang mendorong ritual berikutnya.

Anggaran resource di Compose dan Desktop #

Chapter Resource di Compose memperkenalkan kunci mem_limit dan cpus pada service. Pada lingkungan development multi-project, anggaran eksplisit justru paling terasa manfaatnya — database staging tidak lagi melahap sisa RAM milik project utama:

yaml
services:
  db:
    image: postgres:18-alpine
    mem_limit: 512m
    cpus: 1.5

Di Docker Desktop, langit-langit tertinggi tetap ditetapkan VM yang menjadi rumah seluruh container — diatur lewat Settings → Resources atau berkas .wslconfig sebagaimana dibahas di chapter Instalasi Docker Desktop. Limit per service hidup di dalam langit-langit itu: menaikkan mem_limit melebihi RAM yang dialokasikan Desktop hanya memindahkan masalah dari container ke VM.

Ritual kebersihan resource #

Laptop developerpunya cara sendiri untuk membusuk perlahan: image lama, build cache dari minggu lalu, volume anonim dari eksperimen yang sudah dilupakan. docker system df adalah alat ukurnya:

bash
docker system df

Output yang Dihasilkan:

text
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          27        9         12.4GB    6.21GB (50%)
Containers      11        6         489MB     312MB (63%)
Local Volumes   14        7         2.1GB     812MB (38%)
Build Cache     218       0         4.3GB     4.3GB (100%)

Kolom RECLAIMABLE membaca berapa yang bisa dibebaskan tanpa merusak yang sedang dipakai — persis mekanisme yang dibedah di chapter Membersihkan Resource Image. Untuk kebersihan harian developer, lima perintah ini membentuk ritual yang cukup:

PerintahMembersihkanKapan dipakai
docker image prune -aimage tak dipakai container mana punbulanan, atau sebelum proyek besar
docker builder prune -fseluruh build cachesaat df menunjukkan cache membengkak
docker volume prunevolume anonim yang tak terpasanghati-hati: data anonim lenyap
docker system prunecontainer berhenti + jaringan tak terpakai + image danglingrapikan sisa eksperimen
docker compose down -vcontainer + jaringan + volume projectkhusus project uji, bukan dev utama

Ritual yang sehat untuk sebagian besar tim cukup satu paragraf: docker compose ls untuk melihat yang masih hidup, down untuk project yang selesai dipakai, docker system df setiap pekan, dan docker builder prune -f setiap kali angka Build Cache menembus beberapa gigabyte. Sisanya biarkan Docker yang mengurus.

Dengan peta environment, berkas lokal, anggaran resource, dan ritual kebersihan di tempatnya, perjalanan Section ini genap: kita mulai dari siklus edit–rebuild–test yang nyaman, menempuh bind mount dan hot reload, memisahkan image dev dan produksi, belajar mendebug di dalam container, menjalankan test dengan database sekali pakai, dan menutupnya dengan tata kelola lintas mesin. Ada satu sudut yang belum sempat kita soroti dan justru menunggu di ujung koridor: semua kenyamanan ini berdiri di atas asumsi bahwa container itu aman — padahal container berbagi kernel dengan host, .env menyimpan teks polos, port debug terbuka, dan docker.sock menunggu disalahgunakan. Section Keamanan Docker mengangkat satu per satu lapisan itu, dimulai dari prinsip dasarnya.

Referensi #