CI/CD Laravel: Otomatisasi Deployment dengan Jenkins & Docker

Dalam era modern pengembangan perangkat lunak, Continuous Integration (CI) dan Continuous Deployment (CD) menjadi pilar utama untuk menjamin kecepatan, kualitas, dan reliabilitas dalam proses rilis aplikasi. Artikel ini membahas penerapan CI/CD untuk Laravel 11 menggunakan Jenkins dan Docker sebagai tools utama. Kami akan membangun pipeline otomatis untuk menguji, membangun, dan mendeploy aplikasi Laravel ke production environment dengan mudah dan efisien.
Di awal projek ini, kita akan melakukan proses deployment aplikasi absensi yang dapat dilihat pada repositori berikut: ๐ absensi-karyawan-gps-barcode
๐งฑ Arsitektur yang Digunakan
Berikut adalah komponen utama:
- Laravel 11 sebagai backend framework
- Jenkins sebagai CI/CD automation server
- Docker & Docker Compose untuk environment konsisten
- Caddy untuk reverse proxy dan SSL otomatis
- MySQL 8 sebagai database
๐ณ Struktur File
Berikut file penting dalam proyek:
Dockerfile
โ Build Laravel App dengan PHP 8.3 + Composer + NPMdocker-compose.yml
โ Orkestrasi layanan Laravel, Database, dan Caddyentrypoint.sh
โ Script awal container untuk install dan konfigurasi LaravelJenkinsfile
โ Pipeline otomatis CI/CD
๐ง Dockerfile Laravel
Dockerfile ini membangun image Laravel berbasis php:8.3-fpm
, menginstal ekstensi PHP dan Composer.
FROM php:8.3-fpm
# Install dependencies OS & PHP
RUN apt-get update && apt-get install -y \
git unzip zip curl gnupg ca-certificates \
libzip-dev libpng-dev libonig-dev libxml2-dev libpq-dev \
&& docker-php-ext-install pdo pdo_mysql zip gd bcmath
# Install Composer dari image resmi
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
# Copy semua file project
COPY . .
# Copy entrypoint script
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
# Buka port PHP-FPM
EXPOSE 9000
ENTRYPOINT ["entrypoint.sh"]
CMD ["php-fpm"]
๐ ๏ธ docker-compose.yml
services:
laravel_app:
build:
context: .
dockerfile: Dockerfile
container_name: laravel_app
volumes:
- .:/var/www
networks:
- laravel
depends_on:
- laravel_db
laravel_db:
image: mysql:8.0
environment:
MYSQL_DATABASE: db_absensi_karyawan
MYSQL_USER: laravel
MYSQL_PASSWORD: PasswordKamu
MYSQL_ROOT_PASSWORD: PasswordKamu
volumes:
- ./db_data:/var/lib/mysql
networks:
- laravel
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
- .:/var/www
- ./caddy_data:/data
- ./caddy_config:/config
depends_on:
- laravel_app
networks:
- laravel
networks:
laravel:
๐ช entrypoint.sh
Script untuk setup Laravel saat container dijalankan:
#!/bin/sh
cd /var/www
# Salin .env jika belum ada
[ ! -f .env ] && cp .env.example .env
# Install dependency PHP
composer install
# Generate app key jika belum ada
php artisan key:generate --ansi --force
# Jalankan migrasi dan seeder (opsional)
php artisan migrate --force || true
php artisan db:seed --force || true
# Permission folder runtime Laravel
mkdir -p storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
# Install npm & build assets
apt update && apt install -y npm
npm install
npm run build
# Jalankan perintah yang diberikan ke container
exec "$@"
๐งช Jenkinsfile
pipeline {
agent any
environment {
DOCKER_IMAGE = 'masdika/absensi-karyawan:latest'
REMOTE_DOCKER_HOST = 'ssh://[email protected]'
}
stages {
stage('Clone Repository') {
steps {
withCredentials([usernamePassword(credentialsId: 'github-token', usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PAT')]) {
sh '''
rm -rf absensi-karyawan-gps-barcode
git clone https://$GIT_USER:[email protected]/masdikaaa/absensi-karyawan-gps-barcode.git
'''
}
}
}
stage('Build Docker Image') {
steps {
sh '''
cd absensi-karyawan-gps-barcode
docker build -t $DOCKER_IMAGE .
'''
}
}
stage('Push to DockerHub') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub-credentials', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
sh '''
echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin
docker push $DOCKER_IMAGE
'''
}
}
}
stage('Deploy to Remote Docker Server') {
steps {
sshagent(credentials: ['ssh-key']) {
sh '''
ssh -o StrictHostKeyChecking=no [email protected] '
set -e
if [ ! -d absensi-app ]; then
git clone https://github.com/masdikaaa/absensi-karyawan-gps-barcode.git absensi-app
fi
cd absensi-app
git reset --hard
git checkout master
git pull origin master
# Pastikan file .env ada
if [ ! -f .env ]; then
echo "[INFO] .env tidak ditemukan, membuat dari .env.example"
cp .env.example .env
fi
docker compose pull
docker compose down
docker compose up -d --build
'
'''
}
}
}
}
}



๐ก Manfaat CI/CD di Jenkins
- ๐ Kecepatan: Build & deploy otomatis setelah push code
- โ Konsistensi: Tidak ada lagi perbedaan environment lokal dan production
- ๐ Keamanan: Caddy otomatis menangani HTTPS
- ๐ฆ Isolasi: Semua dependency Laravel berada dalam container
๐ Penutup
Dengan menggabungkan Laravel, Docker, dan Jenkins, proses pengembangan menjadi lebih profesional dan scalable. Pipeline ini bisa kamu kembangkan dengan integrasi test otomatis, notifikasi ke Slack, atau multi-environment (staging & production).
Selamat mencoba membangun DevOps pipeline profesional untuk Laravel-mu! ๐งโ๐ปโจ

Buat kamu yang lagi Deploy aplikasi dengan Next.js dan pengen jalan di Kubernetes dengan domain custom + SSL otomatis, artikel…

๐ Apa itu Next.js ? Next.js adalah framework React yang populer untuk membangun aplikasi web modern. Dengan fitur SSR (Server…