"Works on my machine" adalah meme developer yang sudah terlalu familiar. Setiap developer baru di tim butuh beberapa jam (atau hari) untuk menyesuaikan environment-nya. Docker menyelesaikan masalah ini dengan mengemas seluruh environment aplikasi ke dalam container yang bisa berjalan identik di mana saja — MacOS, Windows, Linux, maupun server production.

Mengapa Docker untuk Development Laravel?

Sebelum Docker, setup environment Laravel memerlukan instalasi manual PHP (versi spesifik), ekstensi PHP yang dibutuhkan, web server (Nginx/Apache), MySQL, Redis, dan sebagainya. Di mesin berbeda, versi berbeda menyebabkan perilaku berbeda. Docker memberikan:

  • Konsistensi — Semua developer dan server production menggunakan image yang sama
  • Isolasi — Proyek berbeda bisa menggunakan PHP versi berbeda tanpa konflik
  • Reproductibility — Setup environment baru cukup satu perintah: docker compose up
  • Port-ability — Pindah dari satu mesin ke mesin lain tanpa setup ulang

Struktur Docker untuk Laravel

Kita akan membuat setup dengan 4 service: PHP-FPM (aplikasi), Nginx (web server), MySQL (database), dan Redis (cache/queue).

project/
├── docker/
│   ├── nginx/
│   │   └── default.conf
│   └── php/
│       └── Dockerfile
├── docker-compose.yml
└── ... (file Laravel)

docker-compose.yml

services:
  app:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    volumes:
      - .:/var/www/html
      - ./storage:/var/www/html/storage
    depends_on:
      - mysql
      - redis
    environment:
      - APP_ENV=local
    networks:
      - laravel

  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - .:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    networks:
      - laravel

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - laravel

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    networks:
      - laravel

volumes:
  mysql_data:

networks:
  laravel:
    driver: bridge

Dockerfile untuk PHP

FROM php:8.2-fpm

RUN apt-get update && apt-get install -y \
    git curl libpng-dev libonig-dev \
    libxml2-dev zip unzip \
    && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd \
    && pecl install redis \
    && docker-php-ext-enable redis \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

COPY . .

RUN composer install --no-interaction --prefer-dist --optimize-autoloader

RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

EXPOSE 9000
CMD ["php-fpm"]

Konfigurasi Nginx

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

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

    location ~ \.php$ {
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Workflow Development Sehari-hari

# Mulai semua service
docker compose up -d

# Jalankan artisan command
docker compose exec app php artisan migrate

# Masuk ke shell container
docker compose exec app bash

# Lihat log real-time
docker compose logs -f app

# Stop semua service
docker compose down

Tips Optimasi untuk Development

Volume Mounting Performance — Di macOS, bind mounts bisa lambat. Gunakan delegated flag atau pertimbangkan Mutagen untuk sinkronisasi yang lebih cepat.

Xdebug — Tambahkan profil khusus development dengan Xdebug enabled:

  app-debug:
    extends:
      service: app
    environment:
      XDEBUG_MODE: develop,debug
      XDEBUG_CONFIG: client_host=host.docker.internal

Multi-stage Build untuk Production — Gunakan multi-stage Dockerfile untuk memisahkan build dependencies dari runtime image, menghasilkan image yang lebih kecil dan aman untuk production.

Setelah Docker setup selesai, onboarding developer baru cukup: clone repo, copy .env.example ke .env, jalankan docker compose up -d, lalu docker compose exec app php artisan migrate --seed. Selesai dalam 5 menit.