Server/Infra

Docker Compose untuk Development Lokal - Setup Multi-Service dalam 5 Menit

Pernah nggak sih kamu baru join project baru, tapi butuh waktu seharian cuma buat setup environment? Install MySQL, Redis, PHP, Nginx satu-satu. Belum lagi kalau versinya bentrok sama project lain. Saya pernah mengalami ini dan rasanya frustrasi banget. Semua masalah itu selesai ketika saya kenal Docker Compose.

Docker Compose itu tool yang memungkinkan kamu mendefinisikan dan menjalankan multiple container Docker sekaligus, cukup dengan satu file YAML. Bayangkan kamu punya satu file yang bisa langsung spin up MySQL, Redis, PHP-FPM, Nginx, dan bahkan phpMyAdmin dalam hitungan detik. Tanpa install apapun di host machine. Tanpa konflik versi. Tanpa drama.

Kenapa Docker Compose Itu Game Changer untuk Developer

Sebelum kenal Docker Compose, setup development environment itu proses yang menyebalkan. Kamu harus install semua dependency di machine lokal, pastikan versinya cocok, dan kalau ada update, kadang semuanya jadi broken. Dengan Docker Compose, semua environment didefinisikan dalam satu file. Mau ganti dari PHP 8.1 ke PHP 8.3? Tinggal ubah satu baris. Mau tambah Elasticsearch? Tambah beberapa baris config. Selesai.

Keunggulan utama Docker Compose untuk development lokal:

  • Reproducible environment Semua developer di tim punya environment yang identik. Tidak ada lagi "di saya jalan, di kamu nggak"
  • Isolasi per project Project A pakai PHP 7.4 + MySQL 5.7, Project B pakai PHP 8.3 + MySQL 8.0. Keduanya jalan berdampingan tanpa konflik
  • One command setup docker compose up -d dan semua service langsung berjalan. New developer bisa mulai coding dalam 5 menit
  • Clean uninstall Hapus semua container dan volume, machine kamu bersih kembali tanpa sisa-sisa installasi

Instalasi Docker dan Docker Compose

Sebelum mulai, pastikan Docker sudah terinstall. Di Linux (Ubuntu/Debian), jalankan perintah berikut:


# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Tambahkan user ke docker group (tanpa sudo)
sudo usermod -aG docker $USER

# Logout dan login ulang, lalu verify
docker --version
docker compose version

Untuk macOS dan Windows, tinggal download Docker Desktop dari docker.com. Docker Compose sudah included di dalamnya, jadi tidak perlu install terpisah.

Verify instalasi berhasil:


docker --version
# Docker version 27.x.x

docker compose version
# Docker Compose version v2.x.x

Anatomy File docker-compose.yml

File docker-compose.yml (atau compose.yaml di versi baru) adalah jantung dari Docker Compose. Di dalam file ini kamu mendefinisikan semua service, network, dan volume yang dibutuhkan project. Mari kita bedah strukturnya:


services:
 # Nama service (bebas, ini jadi hostname di internal network)
 app:
 image: php:8.3-fpm # Docker image yang digunakan
 volumes:
 - ./:/var/www/html # Mount folder project ke container
 networks:
 - app-network # Network yang diikuti

 nginx:
 image: nginx:alpine
 ports:
 - "8080:80" # Port mapping host:container
 volumes:
 - ./:/var/www/html
 - ./nginx.conf:/etc/nginx/conf.d/default.conf
 depends_on:
 - app # Pastikan app berjalan dulu
 networks:
 - app-network

networks:
 app-network:
 driver: bridge

Setiap service yang didefinisikan akan punya hostname sesuai nama servicenya. Jadi kalau service app berjalan di port 9000, service lain bisa mengaksesnya via app:9000. Ini sangat powerful karena kamu nggak perlu pusing soal IP address internal.

Setup Lengkap: PHP + MySQL + Redis + Nginx

Sekarang kita bikin setup yang real-world. Sebuah environment lengkap untuk development aplikasi web PHP dengan database MySQL, caching Redis, dan web server Nginx. Ini setup yang paling banyak dipakai di project-project Indonesian web development:


services:
 # PHP-FPM Application Server
 app:
 build:
 context: .
 dockerfile: Dockerfile
 container_name: myapp-php
 volumes:
 - ./:/var/www/html
 - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
 networks:
 - myapp-network
 restart: unless-stopped

 # Nginx Web Server
 nginx:
 image: nginx:alpine
 container_name: myapp-nginx
 ports:
 - "8080:80"
 volumes:
 - ./:/var/www/html
 - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
 depends_on:
 - app
 networks:
 - myapp-network
 restart: unless-stopped

 # MySQL Database
 database:
 image: mysql:8.0
 container_name: myapp-mysql
 ports:
 - "3306:3306"
 environment:
 MYSQL_ROOT_PASSWORD: rootsecret123
 MYSQL_DATABASE: myapp_db
 MYSQL_USER: myapp_user
 MYSQL_PASSWORD: myapp_pass123
 volumes:
 - mysql-data:/var/lib/mysql
 - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
 networks:
 - myapp-network
 restart: unless-stopped

 # Redis Cache
 redis:
 image: redis:7-alpine
 container_name: myapp-redis
 ports:
 - "6379:6379"
 command: redis-server --requirepass redissecret123
 volumes:
 - redis-data:/data
 networks:
 - myapp-network
 restart: unless-stopped

 # phpMyAdmin (opsional, untuk debugging)
 phpmyadmin:
 image: phpmyadmin/phpmyadmin
 container_name: myapp-pma
 ports:
 - "8081:80"
 environment:
 PMA_HOST: database
 PMA_USER: myapp_user
 PMA_PASSWORD: myapp_pass123
 depends_on:
 - database
 networks:
 - myapp-network
 restart: unless-stopped

volumes:
 mysql-data:
 redis-data:

networks:
 myapp-network:
 driver: bridge

Perhatikan beberapa hal penting di config di atas:

  • Volumes untuk persistence mysql-data dan redis-data memastikan data tidak hilang saat container di-restart. Tanpa volume ini, semua data hilang setiap kali docker compose down
  • depends_on Memastikan service dependency berjalan dulu. Nginx butuh PHP-FPM, phpMyAdmin butuh MySQL
  • Network terpisah Semua service berada di network yang sama sehingga bisa saling berkomunikasi via hostname
  • restart: unless-stopped Container otomatis restart kalau crash, tapi tetap mati kalau kamu stop manual

Custom Dockerfile untuk PHP

Image php:8.3-fpm itu basic. Kamu hampir selalu butuh menambahkan extension seperti PDO, Redis, GD, dll. Buat file Dockerfile di root project:


FROM php:8.3-fpm

# Install system dependencies
RUN apt-get update && apt-get install -y \
 git \
 curl \
 libpng-dev \
 libjpeg-dev \
 libfreetype6-dev \
 libonig-dev \
 libxml2-dev \
 libzip-dev \
 zip \
 unzip \
 && docker-php-ext-configure gd --with-freetype --with-jpeg \
 && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \
 && pecl install redis \
 && docker-php-ext-enable redis \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /var/www/html

# Set proper permissions
RUN chown -R www-data:www-data /var/www/html

EXPOSE 9000
CMD ["php-fpm"]

Dockerfile ini melakukan beberapa hal sekaligus: install system library yang dibutuhkan, compile PHP extension, pasang Composer, dan set permissions yang benar. Semua terjadi di build time, jadi container yang dihasilkan sudah siap pakai.

Konfigurasi Nginx untuk PHP-FPM

Buat folder nginx/ dan file default.conf:


server {
 listen 80;
 server_name localhost;
 root /var/www/html/public;
 index index.php index.html;

 location / {
 try_files $uri $uri/ /index.php?$query_string;
 }

 location ~ \.php$ {
 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 fastcgi_pass app:9000;
 fastcgi_index index.php;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_param PATH_INFO $fastcgi_path_info;
 }

 location ~ /\.ht {
 deny all;
 }
}

Perhatikan fastcgi_pass app:9000 ini merujuk ke service app yang kita definisikan di compose file. Docker network memungkinkan komunikasi antar container via nama service. Nggak perlu tahu IP addressnya.

Menjalankan dan Mengelola Environment

Sekarang saatnya menjalankan semuanya. Pastikan semua file sudah tersimpan di folder project:


# Build dan start semua container
docker compose up -d --build

# Lihat status container
docker compose ps

# Lihat log semua service
docker compose logs -f

# Lihat log satu service saja
docker compose logs -f app

# Masuk ke container PHP
docker compose exec app bash

# Jalankan artisan/migration (Laravel)
docker compose exec app php artisan migrate

# Jalankan composer install di dalam container
docker compose exec app composer install

# Stop semua container
docker compose down

# Stop DAN hapus semua data (hati-hati!)
docker compose down -v

Setelah semua container berjalan, buka browser dan akses http://localhost:8080. Kalau pakai Laravel atau framework lain yang punya public/ folder, app langsung bisa diakses. phpMyAdmin tersedia di http://localhost:8081.

Hot Reload: Edit File Langsung Ter-Reflect

Salah satu keunggulan Docker Compose untuk development adalah volume mounting. Ketika kamu mount folder project ke container dengan:


volumes:
 - ./:/var/www/html

Setiap perubahan file di host machine langsung ter-reflect di container. Edit file di VS Code, save, refresh browser perubahan langsung terlihat. Nggak perlu rebuild container setiap kali edit code. Ini yang bikin workflow development dengan Docker Compose terasa seamless.

Docker Compose Profiles: Satu File untuk Semua Kebutuhan

Kadang kamu nggak butuh semua service sekaligus. Misalnya, saat development biasa kamu butuh PHP + MySQL + Redis. Tapi saat debugging database, kamu butuh phpMyAdmin juga. Docker Compose profiles solusinya:


services:
 app:
 # ... config biasa

 database:
 # ... config biasa

 redis:
 # ... config biasa

 phpmyadmin:
 image: phpmyadmin/phpmyadmin
 profiles:
 - debug
 # ... config lainnya

 mailhog:
 image: mailhog/mailhog
 profiles:
 - debug
 ports:
 - "1025:1025"
 - "8025:8025"

# Jalankan service biasa saja (tanpa debug tools)
docker compose up -d

# Jalankan semua termasuk debug tools
docker compose --profile debug up -d

Ini sangat berguna saat kamu punya service yang hanya dibutuhkan sesekali. MailHog untuk testing email, Selenium untuk testing browser, atau Elasticsearch untuk full-text search. Semua bisa diaktifkan sesuai kebutuhan tanpa mengubah file.

Environment Variables dan Secrets

Jangan hardcode password dan secret di dalam docker-compose.yml. Gunakan file .env di folder project:


# .env file
DB_ROOT_PASSWORD=supersecretroot
DB_NAME=myapp_db
DB_USER=myapp_user
DB_PASSWORD=myapppassword
REDIS_PASSWORD=redispassword123
APP_PORT=8080
PMA_PORT=8081

Lalu referensikan di compose file:


services:
 database:
 image: mysql:8.0
 ports:
 - "3306:3306"
 environment:
 MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
 MYSQL_DATABASE: ${DB_NAME}
 MYSQL_USER: ${DB_USER}
 MYSQL_PASSWORD: ${DB_PASSWORD}

 nginx:
 ports:
 - "${APP_PORT}:80"

Penting: Tambahkan .env ke .gitignore. Jangan pernah commit secrets ke repository. Buat file .env.example dengan nilai placeholder sebagai dokumentasi untuk developer lain.

Tips dan Trik dari Pengalaman

Setelah pakai Docker Compose di belasan project, ini beberapa tips yang saya pelajari:

  • Gunakan named volumes, bukan bind mounts untuk database Bind mount (./data:/var/lib/mysql) sering bermasalah dengan permission. Named volume (mysql-data:/var/lib/mysql) lebih reliable
  • Pin versi image Jangan pakai mysql:latest karena bisa berubah sewaktu-waktu. Pakai mysql:8.0 atau bahkan mysql:8.0.36 untuk konsistensi
  • Pakai .dockerignore Buat file .dockerignore untuk exclude node_modules, vendor, dan .git dari build context. Ini mempercepat build secara signifikan
  • Jangan jalankan production di Docker Compose Docker Compose bagus untuk development dan testing. Untuk production, gunakan Kubernetes, Docker Swarm, atau managed container service
  • Backup volume secara berkala Jalankan docker compose exec database mysqldump -u root -p dbname > backup.sql sebelum melakukan perubahan besar

Troubleshooting Umum

Beberapa masalah yang sering muncul dan solusinya:

  • Port sudah dipakai Ganti port mapping di compose file. Misalnya MySQL conflict, pakai "3307:3306" di host
  • Permission denied pada volume Tambahkan user mapping di compose: user: "${UID}:${GID}" atau set ownership di Dockerfile
  • Container langsung exit Cek log dengan docker compose logs nama_service. Biasanya error di config atau missing dependency
  • Network tidak bisa resolve hostname Pastikan semua service ada di network yang sama. Cek dengan docker network inspect nama_network

Kesimpulan

Docker Compose mengubah cara saya bekerja sebagai developer. Dari yang dulunya butuh waktu berjam-jam setup environment, sekarang cukup satu perintah. Semua service berjalan dengan versi yang tepat, terisolasi dari system lokal, dan bisa di-share ke seluruh tim via git. Kalau kamu belum pakai Docker Compose untuk development lokal, sekarang waktu yang tepat untuk mulai. File docker-compose.yml di atas bisa langsung kamu copy dan sesuaikan dengan kebutuhan projectmu. Selamat mencoba!


You may also like


0 Comments


Leave a Reply

Comments with links or spam keywords will be rejected.
Scroll to Top