HOSTING CEPATDOMAIN MURAHSSL GRATISSUPPORT 24/7UPTIME 99.9%SERVER INDONESIAHOSTING CEPATDOMAIN MURAHSSL GRATISSUPPORT 24/7UPTIME 99.9%SERVER INDONESIA
Tutorial

Tutorial Docker Compose: Cara Menjalankan Multi-Container Aplikasi

Tim HostingEkspres|5 Juni 2026|13 menit baca
docker compose tutorialbelajar docker composedocker-compose.ymlmulti container dockerdocker compose indonesiadocker stack vpsdocker compose nodejsdocker compose mysql
Tutorial Docker Compose: Cara Menjalankan Multi-Container Aplikasi
📚 Baca juga: Cara Setup Docker di Vps | Cara Setup Vps | Cara Membuat Website

Apa Itu Docker Compose dan Mengapa Anda Membutuhkannya?

Ketika aplikasi Anda tumbuh melampaui satu container, mengelola container satu per satu dengan perintah docker run menjadi tidak praktis. Bayangkan aplikasi web modern yang terdiri dari: container Node.js untuk backend, container React untuk frontend, container MySQL untuk database, container Redis untuk caching, dan container Nginx sebagai reverse proxy - menjalankan dan mengatur semua container ini secara manual setiap kali sangat melelahkan dan rawan kesalahan.

Docker Compose adalah tool yang memungkinkan Anda mendefinisikan dan menjalankan seluruh stack aplikasi multi-container menggunakan satu file konfigurasi YAML bernama docker-compose.yml. Dengan satu perintah docker compose up, seluruh stack langsung berjalan - lengkap dengan network, volume, environment variable, dan dependency antar service yang sudah dikonfigurasi. Tutorial Docker Compose ini mencakup semua yang Anda butuhkan untuk mulai produktif.

Prasyarat: Docker sudah terinstal di sistem Anda (VPS atau lokal). Docker Compose Plugin sudah termasuk dalam instalasi Docker Engine modern dan dipanggil dengan docker compose (tanpa tanda hubung). Panduan ini menggunakan sintaks Compose v2 yang merupakan standar saat ini.

Struktur File docker-compose.yml

File docker-compose.yml menggunakan format YAML dan memiliki beberapa blok utama:

docker compose tutorial
Ilustrasi docker compose tutorial
version: "3.9"  # Versi spec Compose (opsional di Compose v2+)

services:       # Daftar container/service yang akan dijalankan
  nama-service:
    image: nama-image:tag     # Gunakan image siap pakai, ATAU
    build: ./path/ke/dir      # Build dari Dockerfile
    ports:
      - "host:container"
    environment:
      - NAMA_VAR=nilai
    volumes:
      - nama-volume:/path/di/container
    depends_on:
      - service-lain
    networks:
      - nama-network
    restart: unless-stopped

volumes:        # Definisi named volumes
  nama-volume:

networks:       # Definisi custom networks
  nama-network:
    driver: bridge

Indentasi sangat penting di YAML - gunakan spasi (bukan tab) secara konsisten. Dua spasi per level indentasi adalah konvensi yang paling umum digunakan.

Contoh 1: Stack Laravel + MySQL + Redis

Mari mulai dengan contoh praktis yang relevan bagi developer Indonesia: stack Laravel dengan MySQL dan Redis:

# Buat direktori proyek
mkdir ~/laravel-stack && cd ~/laravel-stack

# Buat struktur direktori
mkdir -p src nginx/conf.d

Buat file docker-compose.yml:

cat > docker-compose.yml << 'EOF'
version: "3.9"

services:
  # Nginx sebagai reverse proxy dan web server
  nginx:
    image: nginx:1.25-alpine
    container_name: laravel-nginx
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./src:/var/www/html
      - ./nginx/conf.d:/etc/nginx/conf.d
    depends_on:
      - app
    networks:
      - laravel-net

  # PHP-FPM untuk Laravel
  app:
    build:
      context: .
      dockerfile: Dockerfile.app
    container_name: laravel-app
    restart: unless-stopped
    working_dir: /var/www/html
    volumes:
      - ./src:/var/www/html
    environment:
      - APP_ENV=production
      - APP_KEY=${APP_KEY}
      - DB_CONNECTION=mysql
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_DATABASE=${DB_DATABASE}
      - DB_USERNAME=${DB_USERNAME}
      - DB_PASSWORD=${DB_PASSWORD}
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - laravel-net

  # MySQL database
  mysql:
    image: mysql:8.0
    container_name: laravel-mysql
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - laravel-net

  # Redis untuk caching dan session
  redis:
    image: redis:7-alpine
    container_name: laravel-redis
    restart: unless-stopped
    volumes:
      - redis-data:/data
    networks:
      - laravel-net

volumes:
  mysql-data:
  redis-data:

networks:
  laravel-net:
    driver: bridge
EOF

Buat file .env untuk menyimpan nilai yang sensitif:

cat > .env << 'EOF'
APP_KEY=base64:ganti-dengan-key-laravel-anda
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=UserPass789Kuat
DB_ROOT_PASSWORD=RootPass123Kuat
EOF

Contoh 2: Stack Node.js + MongoDB + Nginx

Contoh kedua untuk developer yang menggunakan stack JavaScript modern dengan MongoDB:

cat > docker-compose.yml << 'EOF'
version: "3.9"

services:
  nginx:
    image: nginx:1.25-alpine
    container_name: node-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - api
    networks:
      - app-net

  api:
    build: ./api
    container_name: node-api
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - PORT=3000
      - MONGO_URI=mongodb://mongo:27017/appdb
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      - mongo
    networks:
      - app-net
    # Tidak expose port ke host - hanya diakses via Nginx
    expose:
      - "3000"

  mongo:
    image: mongo:7.0
    container_name: node-mongo
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
      MONGO_INITDB_DATABASE: appdb
    volumes:
      - mongo-data:/data/db
    networks:
      - app-net

volumes:
  mongo-data:

networks:
  app-net:
    driver: bridge
EOF

Perintah Docker Compose yang Paling Sering Digunakan

Berikut referensi lengkap perintah Docker Compose untuk operasional sehari-hari. Semua perintah dijalankan dari direktori yang berisi file docker-compose.yml:

# Menjalankan seluruh stack (download image, build, dan start)
docker compose up

# Menjalankan stack di background (detached mode)
docker compose up -d

# Membangun ulang image sebelum menjalankan (setelah perubahan kode)
docker compose up -d --build

# Menghentikan semua container dalam stack
docker compose down

# Menghentikan dan menghapus volumes (HATI-HATI: menghapus data!)
docker compose down -v

# Melihat status semua service dalam stack
docker compose ps

# Melihat log semua service
docker compose logs

# Melihat log service tertentu dan ikuti output real-time
docker compose logs -f app

# Restart service tertentu
docker compose restart app

# Menghentikan service tertentu
docker compose stop mysql

# Memulai kembali service yang berhenti
docker compose start mysql

# Menjalankan perintah di dalam container service yang berjalan
docker compose exec app bash
docker compose exec app php artisan migrate

# Menjalankan perintah di container baru (tidak perlu service sedang running)
docker compose run --rm app php artisan key:generate

# Melihat resource usage semua container dalam stack
docker compose top

# Melihat konfigurasi yang sudah di-resolve (berguna untuk debug)
docker compose config

# Scale service tertentu ke beberapa instance
docker compose up -d --scale api=3

Menggunakan Environment Variables dengan File .env

Docker Compose secara otomatis membaca file .env di direktori yang sama dan menggunakan nilainya untuk substitusi variabel dalam docker-compose.yml. Ini adalah cara terbaik mengelola konfigurasi yang berbeda antara development dan production:

# .env untuk development
cat > .env.development << 'EOF'
APP_ENV=local
DB_DATABASE=myapp_dev
DB_USERNAME=dev_user
DB_PASSWORD=dev_password_local
DEBUG=true
EOF

# .env untuk production
cat > .env.production << 'EOF'
APP_ENV=production
DB_DATABASE=myapp_prod
DB_USERNAME=prod_user
DB_PASSWORD=PasswordSangatKuatProduction!
DEBUG=false
EOF

# Gunakan file .env tertentu
docker compose --env-file .env.production up -d

Jangan pernah commit file .env yang berisi nilai production ke version control (Git). Tambahkan .env dan .env.* ke .gitignore. Untuk CI/CD, inject environment variables melalui platform secrets (GitHub Actions secrets, GitLab CI variables, dll).

docker compose tutorial
Ilustrasi docker compose tutorial

Healthcheck dan Dependency Ordering

Salah satu masalah umum dengan Docker Compose adalah service yang bergantung pada service lain (misalnya app yang membutuhkan database) kadang mencoba connect sebelum database siap menerima koneksi. Solusinya adalah menggunakan healthcheck dan depends_on dengan kondisi:

services:
  mysql:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 10s      # Cek setiap 10 detik
      timeout: 5s        # Timeout jika tidak ada respons dalam 5 detik
      retries: 5         # Coba maksimal 5 kali sebelum dianggap unhealthy
      start_period: 30s  # Beri waktu 30 detik untuk startup awal

  app:
    depends_on:
      mysql:
        condition: service_healthy  # Tunggu hingga mysql healthcheck pass
      redis:
        condition: service_started  # Cukup tunggu hingga redis container started

Docker Compose untuk Development vs Production

Praktik terbaik adalah memisahkan konfigurasi Compose untuk development dan production menggunakan multiple Compose files:

# docker-compose.yml - konfigurasi base (shared)
# docker-compose.override.yml - override untuk development (dibaca otomatis)
# docker-compose.prod.yml - override untuk production

Buat docker-compose.override.yml untuk development:

cat > docker-compose.override.yml << 'EOF'
version: "3.9"

services:
  app:
    build:
      target: development  # Gunakan stage development di multi-stage Dockerfile
    volumes:
      - ./src:/var/www/html  # Hot-reload: mount kode langsung dari host
    environment:
      - APP_ENV=local
      - APP_DEBUG=true

  # Tambah phpMyAdmin hanya untuk development
  phpmyadmin:
    image: phpmyadmin:latest
    ports:
      - "8080:80"
    environment:
      PMA_HOST: mysql
    networks:
      - laravel-net
EOF

Buat docker-compose.prod.yml untuk production:

cat > docker-compose.prod.yml << 'EOF'
version: "3.9"

services:
  app:
    build:
      target: production  # Gunakan stage production (image lebih kecil, lebih aman)
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "1.0"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
EOF
# Jalankan dengan konfigurasi production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Mengelola Secrets dengan Docker Compose

Untuk informasi sensitif seperti API key dan database password di production, hindari menyimpan nilai langsung di docker-compose.yml atau environment variable yang mudah dibaca. Gunakan Docker Secrets (tersedia di Docker Swarm) atau approach berbasis file:

# Simpan secret dalam file (di luar version control)
echo "PasswordSuperRahasia" > secrets/db_password.txt
chmod 600 secrets/db_password.txt

# Referensikan di docker-compose.yml
services:
  mysql:
    image: mysql:8.0
    secrets:
      - db_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

Backup dan Restore Database dengan Docker Compose

Mengelola backup database di environment Docker Compose:

# Backup database MySQL dari container yang berjalan
docker compose exec mysql mysqldump   -u root -p${DB_ROOT_PASSWORD}   --all-databases   | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz

# Restore database dari backup
gunzip < backup_20260609_020000.sql.gz |   docker compose exec -T mysql mysql   -u root -p${DB_ROOT_PASSWORD}

# Backup volume langsung (lebih universal)
docker run --rm   -v laravel-stack_mysql-data:/data   -v $(pwd):/backup   alpine tar czf /backup/mysql-volume-backup.tar.gz /data

FAQ: Pertanyaan Umum Docker Compose

Apa perbedaan docker-compose (v1) dan docker compose (v2)?

Docker Compose v1 adalah tool terpisah yang diinstal sebagai binary docker-compose (dengan tanda hubung), ditulis dalam Python. Docker Compose v2 adalah reimplementasi dalam Go yang terintegrasi langsung sebagai plugin Docker CLI, dipanggil dengan docker compose (tanpa tanda hubung). Compose v2 jauh lebih cepat, mendukung semua fitur terbaru, dan merupakan standar yang direkomendasikan saat ini. Compose v1 sudah tidak lagi dikembangkan.

Berapa banyak service yang bisa didefinisikan dalam satu docker-compose.yml?

Tidak ada batasan teknis untuk jumlah service dalam satu file Compose. Namun dari sisi praktikalitas, jika stack Anda memiliki lebih dari 10–15 service, pertimbangkan memecahnya menjadi beberapa stack Compose terpisah, atau beralih ke orchestrator yang lebih powerful seperti Kubernetes. Untuk kebanyakan aplikasi web di VPS, 3–7 service sudah mencukupi.

Bagaimana cara menjalankan perintah migrasi database secara otomatis saat stack dimulai?

Ada dua pendekatan umum: (1) Tambahkan perintah migrasi di entrypoint script container app Anda - jalankan migrasi sebelum menjalankan server. (2) Gunakan service sementara (one-shot service) di Compose dengan docker compose run --rm app php artisan migrate setelah stack berjalan. Pendekatan entrypoint script lebih otomatis, sedangkan one-shot service memberi kontrol lebih manual.

Apakah Docker Compose cocok untuk production?

Docker Compose sangat cocok untuk production pada skala single-server (satu VPS). Untuk VPS tunggal dengan traffic sedang, Compose memberikan keseimbangan sempurna antara kemudahan manajemen dan fungsionalitas. Batasan utama Compose adalah tidak mendukung distribusi container ke beberapa server secara native. Jika aplikasi Anda membutuhkan horizontal scaling ke beberapa server, pertimbangkan Docker Swarm (sederhana) atau Kubernetes (lengkap tapi kompleks).

Bagaimana cara update service tertentu tanpa menghentikan service lain?

Gunakan perintah docker compose up -d --build --no-deps nama-service. Flag --no-deps mencegah Compose me-restart service yang bergantung pada service yang diupdate. Contoh: docker compose up -d --build --no-deps app akan rebuild dan restart hanya service app tanpa mengganggu MySQL dan Redis yang sedang berjalan.

Kenapa container app saya selalu gagal connect ke database meskipun sudah pakai depends_on?

depends_on tanpa kondisi hanya menunggu container database dimulai, bukan menunggu database siap menerima koneksi. Database seperti MySQL dan PostgreSQL membutuhkan beberapa detik hingga siap setelah container running. Solusi: tambahkan healthcheck pada service database dan gunakan depends_on: condition: service_healthy pada service yang bergantung, seperti yang dicontohkan di bagian Healthcheck di atas.

Bagaimana cara melihat log dari semua service sekaligus di Docker Compose?

Gunakan docker compose logs -f --tail=100 untuk melihat 100 baris log terakhir dari semua service dan terus mengikuti output baru secara real-time. Untuk log service tertentu: docker compose logs -f --tail=50 app. Untuk menyimpan log ke file: docker compose logs --no-color > stack-logs.txt.

Baca Juga:

Kesimpulan: Docker Compose sebagai Fondasi Deployment Modern

Dengan memahami tutorial Docker Compose ini, Anda kini bisa mendefinisikan, menjalankan, dan mengelola aplikasi multi-container dengan cara yang terstruktur, reproducible, dan mudah di-maintain. File docker-compose.yml menjadi "dokumentasi hidup" dari arsitektur aplikasi Anda yang bisa di-commit ke Git dan digunakan oleh seluruh anggota tim.

Untuk menjalankan Docker Compose stack di VPS production, pastikan server Anda memiliki spesifikasi yang memadai. VPS HostingEkspres tersedia dengan berbagai pilihan RAM dan CPU yang cocok untuk berbagai ukuran stack - mulai dari proyek personal hingga aplikasi bisnis. Langkah selanjutnya: pelajari cara deploy Docker container ke VPS production dengan strategi zero-downtime dan CI/CD otomatis.

Butuh Hosting untuk Website Anda?

Dapatkan hosting cepat, aman, dan terpercaya dengan harga terjangkau. Gratis domain, SSL, dan support 24/7.

Jangan Ketinggalan Promo!

Subscribe newsletter kami dan dapatkan diskon hingga 50% untuk pembelian pertama kamu.

Gratis, tanpa spam. Bisa unsubscribe kapan saja.