Deploy Laravel ke VPS dengan Docker
Panduan step-by-step deploy aplikasi Laravel menggunakan Docker dan Nginx di VPS. Termasuk setup SSL, environment, dan best practices.
Deploy Laravel ke VPS dengan Docker
Setelah mengerjakan banyak project Laravel, saya menemukan bahwa Docker adalah cara paling reliable untuk deployment. Di artikel ini, saya akan share setup yang saya gunakan di production.
Kenapa Docker untuk Laravel?
Problem yang sering terjadi:
- “Di laptop saya jalan” syndrome
- Dependency conflict antar project
- Setup environment yang memakan waktu
Docker menyelesaikan ini dengan:
- Environment yang konsisten di semua stage
- Isolasi sempurna antar project
- Deployment yang reproducible
Architecture Decision
Saya memilih arsitektur ini karena:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Nginx │───▶│ PHP-FPM │───▶│ MySQL │
│ (Proxy) │ │ (Laravel) │ │ (Database) │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ Redis │
│ (Cache) │
└─────────────┘
💡 Trade-off: Saya pilih PHP-FPM daripada PHP built-in server karena performance lebih baik untuk production workload.
Dockerfile untuk Laravel
FROM php:8.2-fpm-alpine
# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql opcache
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
# Copy composer files first (untuk caching)
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts
# Copy application code
COPY . .
# Optimize Laravel
RUN php artisan config:cache && \
php artisan route:cache && \
php artisan view:cache
# Permission fix
RUN chown -R www-data:www-data storage bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
Docker Compose Setup
version: '3.8'
services:
app:
build: .
volumes:
- ./storage:/var/www/html/storage
environment:
- APP_ENV=production
- DB_HOST=mysql
- REDIS_HOST=redis
depends_on:
- mysql
- redis
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
volumes:
mysql_data:
Nginx Configuration
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
root /var/www/html/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}
Lessons Learned
Setelah deploy beberapa project dengan setup ini:
→ “Selalu test Docker build di CI sebelum push ke production”
→ “Log ke stdout agar mudah di-debug via Docker logs”
→ “Database seeding harus idempotent untuk production”
Deployment Script
#!/bin/bash
set -e
echo "📦 Pulling latest code..."
git pull origin main
echo "🏗️ Building containers..."
docker compose build --no-cache
echo "🔄 Migrating database..."
docker compose run --rm app php artisan migrate --force
echo "🚀 Starting services..."
docker compose up -d
echo "✅ Deployment complete!"
Kesimpulan
Docker + Laravel adalah kombinasi powerful untuk production deployment. Setup awal memang perlu effort, tapi manfaat jangka panjangnya sangat worth it:
- Zero downtime deployment
- Easy rollback
- Consistent environment
- Scalable architecture
Kalau ada pertanyaan, feel free to reach out!