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. Kita 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
๐ Persiapan Credential CI/CD
Agar pipeline dapat berjalan dengan aman dan otomatis, kita perlu menyiapkan 3 jenis credential utama di Jenkins:
- SSH Key (akses ke server Docker)
- GitHub Token (akses ke repository privat)
- Docker Hub Credentials (push image)
๐ Cara Menambahkan Credential di Jenkins
- Masuk ke Jenkins
- Klik Manage Jenkins โ Manage Credentials
- Pilih scope (misalnya:
(global)
atau folder tertentu) - Klik (+) Add Credentials
- Pilih jenis credential sesuai kebutuhan:
โ SSH Key untuk Akses Server Docker
- Kind: SSH Username with private key
- ID:
ssh-key
(wajib sama dengan yang di Jenkinsfile) - Username:
root
(atau user server kamu) - Private Key: paste isi
~/.ssh/id_ed25519
โ GitHub Personal Access Token (PAT)
- Kind: Username with password
- ID:
github-token
- Username: username GitHub kamu
- Password: isi dengan PAT (token) GitHub
(Buat di: https://github.com/settings/tokens)
โ Docker Hub Credential
- Kind: Username with password
- ID:
dockerhub-credentials
- Username: username Docker Hub
- Password: password akun Docker Hub kamu
๐ Dokumentasi resmi Jenkins soal credential bisa kamu baca di sini:
๐ https://www.jenkins.io/doc/book/using/using-credentials/
๐งฑ 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! ๐งโ๐ปโจ