Docker Compose untuk Pemula: dari Nol Sampai Jalan
Daftar Isi
- Apa Itu Docker Compose? (dan Kenapa Kamu Butuh Ini)
- Docker Compose vs docker run Manual
- Compose V2 vs V1 — Pakai yang Mana?
- Prasyarat
- Install Docker Engine
- Verifikasi Compose V2
- Anatomi File docker-compose.yml
- Networks (Kapan Perlu, Kapan Tidak)
- depends_on (Urutan Startup)
- Hands-on #1: Static Website dengan Nginx
- Hands-on #2: App + Database (Node.js + PostgreSQL)
- Hands-on #3: Full Stack (Frontend + Backend + DB + Adminer)
- Perintah Docker Compose yang Wajib Dihapal
- Error Umum & Cara Mengatasinya
- "port is already allocated"
- "no such service: xxx"
- Volume permission denied
- Container exit code 137 (OOM Killed)
- Docker Compose vs Dockerfile — Bedanya Apa?
- Tips & Best Practices
- Langkah Selanjutnya
Docker Compose untuk Pemula: dari Nol Sampai Jalan
Oke sobat, jadi kamu udah berhasil install Docker — selamat. Tapi coba bayangin: kamu punya app yang butuh database PostgreSQL, Redis buat caching, plus Nginx di depannya. Jalanin docker run satu-satu? Dengan flag -p, -v, --network... tiga container aja udah bikin terminal kamu penuh command sepanjang rel kereta.
Nah, Docker Compose hadir buat ngatasi persis masalah itu. Satu file YAML, satu command, semua container jalan bareng. Dan di tutorial ini, kamu bakal langsung praktek — bukan cuma teori.
Yang kita bahas:
- Apa itu Docker Compose (dan bedanya sama Dockerfile)
- Setup dari nol (Compose V2, 2026-ready)
- 3 hands-on project: dari simpel sampai full stack
- Troubleshooting error yang pasti kamu temuin
Siap? Langsung gas.
Apa Itu Docker Compose? (dan Kenapa Kamu Butuh Ini)
Kalau Docker itu kayak masak satu menu, Docker Compose itu buku resep lengkap buat satu meja makan. Kamu definisiin semua "hidangan" (container) di satu file — siapa butuh apa, siapa jalan duluan, siapa ngomong sama siapa — terus tinggal docker compose up. Done.
Secara teknis: Docker Compose adalah tool buat define dan run multi-container Docker applications. Kamu tulis konfigurasi di file docker-compose.yml, dan Compose yang handle sisanya — networking, volume, urutan startup.
Docker Compose vs docker run Manual
| Aspek | docker run manual |
Docker Compose |
|---|---|---|
| Setup | Ketik command per container | 1 file YAML |
| Reproducible | Harus ingat/catat semua flags | File = dokumentasi |
| Networking | Bikin network manual, connect manual | Auto-created, semua service bisa saling reach |
| Start/Stop | docker stop satu-satu |
docker compose down — beres semua |
| Scaling | Manual | docker compose up --scale web=3 |
Compose V2 vs V1 — Pakai yang Mana?
Kalau kamu masih lihat tutorial yang pakai docker-compose (pakai strip), itu Compose V1 — sudah deprecated sejak 2023. Sekarang yang benar:
# V2 (yang kita pakai) — built-in ke Docker CLI
docker compose version
# V1 (deprecated, jangan pakai)
docker-compose --version
Compose V2 itu plugin bawaan Docker Engine. Gak perlu install terpisah. Kalau kamu install Docker Engine terbaru, Compose V2 udah auto ikut.
Prasyarat
Sebelum mulai, pastikan dua hal ini udah ready:
Install Docker Engine
Kalau belum install Docker, cek artikel Install Docker di Ubuntu dulu. Balik lagi ke sini setelah Docker jalan.
Verifikasi Compose V2
docker compose version
# Output: Docker Compose version v2.x.x
Kalau muncul versi 2.x — kamu siap. Kalau command not found, update Docker Engine kamu ke versi terbaru.
Anatomi File docker-compose.yml
Ini jantungnya Compose. Satu file YAML yang nge-define seluruh stack kamu. Struktur dasarnya:
services:
nama-service:
image: nama-image:tag
ports:
- "host:container"
volumes:
- ./local-folder:/container-path
environment:
- KEY=value
depends_on:
- service-lain
Breakdown:
- services — daftar container yang mau kamu jalankan. Tiap service = 1 container.
- image — Docker image yang dipake (dari Docker Hub atau custom build).
- ports — mapping port host ke container.
"8080:80"artinya akses port 8080 di laptop, nyambung ke port 80 di container. - volumes — mount folder lokal ke dalam container. Data persist walau container dihapus.
- environment — env variables. Bisa juga pakai file
.env. - depends_on — urutan startup. "Jangan jalanin service ini sebelum yang itu ready."
Networks (Kapan Perlu, Kapan Tidak)
By default, Compose bikin satu network untuk semua service di file yang sama. Artinya semua service bisa saling communicate pakai nama service sebagai hostname. Kamu gak perlu define network secara eksplisit kecuali:
- Mau isolasi antar grup service
- Mau connect ke network external (misal dari Compose project lain)
depends_on (Urutan Startup)
services:
app:
depends_on:
- db
db:
image: postgres:16
Ini memastikan container db start duluan sebelum app. Tapi perhatian: depends_on cuma nunggu container start, bukan nunggu sampai service di dalamnya ready. Kalau butuh nunggu sampai database beneran accepting connections, pakai healthcheck.
Hands-on #1: Static Website dengan Nginx
Mulai dari yang paling simpel. Kita serve static HTML pakai Nginx.
1. Bikin folder project:
mkdir compose-demo && cd compose-demo
mkdir html
2. Bikin file HTML sederhana:
cat > html/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head><title>Compose Works!</title></head>
<body><h1>Docker Compose berhasil jalan! 🎉</h1></body>
</html>
EOF
3. Bikin docker-compose.yml:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
Penjelasan:
- nginx:alpine — image Nginx yang ringan (~20MB compressed, jauh lebih kecil dari versi Debian ~70MB)
- "8080:80" — akses port 8080 di browser, nyambung ke Nginx di port 80
- ./html:/usr/share/nginx/html:ro — mount folder html kita ke document root Nginx. :ro = read-only (Nginx gak perlu nulis)
4. Jalankan:
docker compose up -d
Flag -d = detached (jalan di background). Tanpa -d, log bakal nempel di terminal.
5. Buka browser: http://localhost:8080
Kalau muncul "Docker Compose berhasil jalan!" — selamat, Compose pertama kamu udah live.
6. Matiin:
docker compose down
Semua container, network yang di-create otomatis — semua di-cleanup. Bersih.
Hands-on #2: App + Database (Node.js + PostgreSQL)
Sekarang naik level. Kita bikin app Node.js yang connect ke PostgreSQL — dua container yang saling ngobrol.
1. Struktur folder:
mkdir compose-app && cd compose-app
mkdir app
2. Bikin app sederhana (app/index.js):
const http = require('http');
const { Pool } = require('pg');
const pool = new Pool({
host: 'db', // nama service di compose = hostname
user: 'myuser',
password: 'mypass',
database: 'mydb',
});
const server = http.createServer(async (req, res) => {
try {
const result = await pool.query('SELECT NOW() as time');
res.end(`DB connected! Server time: ${result.rows[0].time}`);
} catch (err) {
res.end(`DB error: ${err.message}`);
}
});
server.listen(3000, () => console.log('App running on :3000'));
3. app/package.json:
{
"name": "compose-app",
"dependencies": { "pg": "^8.11.0" },
"scripts": { "start": "node index.js" }
}
4. app/Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "start"]
5. docker-compose.yml:
services:
app:
build: ./app
ports:
- "3000:3000"
environment:
- PGHOST=db
- PGUSER=myuser
- PGPASSWORD=mypass
- PGDATABASE=mydb
depends_on:
- db
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Yang baru di sini:
- build: ./app — Compose build image dari Dockerfile di folder ./app
- depends_on — db start duluan
- volumes: pgdata: — named volume. Data PostgreSQL persist walau docker compose down. Kalau pakai docker compose down -v, baru volume ikut dihapus.
6. Jalankan:
docker compose up -d --build
Flag --build paksa rebuild image kalau ada perubahan di Dockerfile/source.
7. Test: http://localhost:3000 — kalau muncul "DB connected! Server time: ..." berarti app berhasil ngomong ke database.
Hands-on #3: Full Stack (Frontend + Backend + DB + Adminer)
Level terakhir. Empat service, custom network, .env file, dan healthcheck.
1. Struktur folder:
fullstack/
├── docker-compose.yml
├── .env
├── frontend/
│ └── index.html
└── backend/
├── Dockerfile
├── package.json
└── index.js
2. File .env (simpan secrets di sini, JANGAN commit ke git):
POSTGRES_USER=admin
POSTGRES_PASSWORD=supersecret123
POSTGRES_DB=fullstack_db
3. docker-compose.yml:
services:
frontend:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./frontend:/usr/share/nginx/html:ro
depends_on:
- backend
networks:
- front-net
backend:
build: ./backend
ports:
- "3000:3000"
env_file:
- .env
depends_on:
db:
condition: service_healthy
networks:
- front-net
- back-net
db:
image: postgres:16-alpine
env_file:
- .env
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
interval: 5s
timeout: 3s
retries: 5
networks:
- back-net
adminer:
image: adminer:latest
ports:
- "8888:8080"
depends_on:
- db
networks:
- back-net
networks:
front-net:
back-net:
volumes:
db-data:
Yang baru dan penting:
- env_file: .env — load environment variables dari file. Lebih aman daripada hardcode di YAML.
- healthcheck — Compose nunggu sampai pg_isready return OK sebelum start backend. Ini solusi masalah "app start tapi DB belum ready".
- condition: service_healthy — depends_on yang beneran nunggu service ready, bukan cuma started.
- Custom networks — frontend cuma bisa reach backend, gak bisa langsung ke db. Isolasi yang proper.
- Adminer — web UI buat manage database. Akses di localhost:8888.
4. Jalankan seluruh stack:
docker compose up -d --build
5. Verifikasi semua jalan:
docker compose ps
Harusnya keempat service status "Up" (atau "Up (healthy)" buat db).
Perintah Docker Compose yang Wajib Dihapal
Ini cheat-sheet yang bakal kamu pakai tiap hari:
| Perintah | Fungsi |
|---|---|
docker compose up -d |
Start semua service (background) |
docker compose down |
Stop + hapus containers & networks |
docker compose down -v |
Sama, tapi hapus volumes juga (data hilang!) |
docker compose ps |
List semua service yang running |
docker compose logs -f |
Live log semua service |
docker compose logs -f app |
Live log service tertentu |
docker compose exec db bash |
Masuk ke shell container db |
docker compose build |
Rebuild semua image |
docker compose restart app |
Restart satu service |
docker compose pull |
Pull image terbaru dari registry |
docker compose config |
Validasi & tampilkan final YAML |
Tips: docker compose logs -f --tail=50 buat lihat 50 baris terakhir + follow realtime. Ini lifesaver waktu debugging.
Error Umum & Cara Mengatasinya
Bagian ini yang jarang dibahas tutorial lain. Padahal kamu pasti ketemu minimal satu dari ini:
"port is already allocated"
Error response from daemon: driver failed programming external connectivity:
Bind for 0.0.0.0:8080 failed: port is already allocated
Penyebab: Port 8080 udah dipake proses lain (mungkin container lama yang belum di-down).
Solusi:
# Cek siapa yang pakai port itu
sudo lsof -i :8080
# atau
docker ps # mungkin container lain masih jalan
# Kill proses yang pakai, atau ganti port di compose:
ports:
- "8081:80" # ganti host port
"no such service: xxx"
Penyebab: Typo di nama service, atau kamu jalankan docker compose di folder yang salah (gak ada docker-compose.yml).
Solusi:
- Cek kamu di folder yang benar
- Cek indentasi YAML (YAML sensitif soal spasi)
- docker compose config buat validasi file
Volume permission denied
PermissionError: [Errno 13] Permission denied: '/data'
Penyebab: Container jalan sebagai user tertentu tapi folder mount-nya punya permission berbeda.
Solusi:
# Opsi 1: Ubah ownership folder lokal
sudo chown -R 1000:1000 ./data
# Opsi 2: Tambah user mapping di compose
services:
app:
user: "1000:1000"
Container exit code 137 (OOM Killed)
Penyebab: Container kehabisan memory. Docker (atau OS) kill paksa.
Solusi:
services:
app:
deploy:
resources:
limits:
memory: 512M # set limit eksplisit
Atau cek app kamu ada memory leak gak — 137 itu selalu soal RAM.
Docker Compose vs Dockerfile — Bedanya Apa?
Ini pertanyaan yang sering banget muncul, terutama buat yang baru belajar. Simpelnya:
| Dockerfile | Docker Compose | |
|---|---|---|
| Fungsi | Bikin satu image custom | Orchestrate banyak container |
| Isinya | Instruksi build (FROM, RUN, COPY) | Deklarasi services (image, ports, volumes) |
| Output | 1 Docker image | Multi-container app yang running |
| Analogi | Resep bikin satu masakan | Menu lengkap satu meja makan |
Kapan pakai Dockerfile?
- Kamu butuh image custom (install dependencies, copy source code, dll)
- App kamu gak tersedia di Docker Hub
Kapan pakai Docker Compose?
- Kamu jalankan lebih dari 1 container yang saling terhubung
- Kamu mau reproducible setup (tinggal docker compose up)
Kombinasi keduanya? Itu yang paling umum. Compose pakai build: buat point ke Dockerfile, kayak di Hands-on #2 dan #3 di atas.
Tips & Best Practices
Beberapa hal yang bakal bikin hidup kamu lebih gampang:
1. Selalu pakai .env untuk secrets
Jangan hardcode password di docker-compose.yml. Pakai .env file dan tambahkan ke .gitignore:
echo ".env" >> .gitignore
2. Pin image version
# ❌ Jangan
image: postgres:latest
# ✅ Pakai versi spesifik
image: postgres:16-alpine
:latest bisa berubah kapan aja tanpa kamu tau. Satu hari jalan, besok tiba-tiba break.
3. Named volumes untuk data persist
volumes:
db-data: # ini named volume — survive docker compose down
Kalau pakai bind mount (./data:/var/lib/...), permission sering jadi masalah. Named volumes lebih aman untuk database.
4. docker compose logs -f untuk debugging
Kalau ada service yang gak mau start, SELALU cek log dulu:
docker compose logs -f nama-service
90% masalah ketahuan dari sini.
5. Pakai docker compose config sebelum up
docker compose config
Ini validasi YAML kamu dan tampilkan final config setelah variable substitution. Tangkap error sebelum runtime.
Langkah Selanjutnya
Kamu udah bisa bikin multi-container app dengan Docker Compose — dari static site sampai full stack dengan healthcheck dan network isolation. Itu udah cover 80% use case development sehari-hari.
Mau lanjut lebih dalam? Beberapa topik yang worth dipelajari:
- Docker networking deep-dive — custom bridge, overlay network untuk multi-host
- Multi-stage build — bikin image production yang kecil dan aman
- Deploy ke VPS — dari laptop ke server pakai Compose + SSH
- Docker Compose Watch — auto-rebuild saat code berubah (hot reload untuk container)
BACA JUGA:
- Cara Install Docker di Ubuntu 24.04
- Setup WSL2 + Arch Linux untuk Ngoding
Segitu dulu sobat. Kalau ada yang stuck atau error aneh, drop di kolom komentar. Error Docker itu pattern-nya mirip-mirip — kemungkinan besar gue atau pembaca lain bisa bantu.
Semoga bermanfaat! 🐳
Artikel ini menggunakan Docker Compose V2 (versi 2.x) yang merupakan standar sejak 2023. Semua command sudah diverifikasi di Docker Engine 24+ pada Ubuntu 22.04/24.04.
Sumber referensi:
- Docker Compose Documentation — Official docs
- Compose File Reference — Spesifikasi lengkap YAML
- Docker Compose Networking — Deep-dive networking
Post a Comment for "Docker Compose untuk Pemula: dari Nol Sampai Jalan"
Mohon berkomentar yang relavan dan tidak menaruh link hidup yah ^_^