Membangun Aplikasi PHP Laravel Berkinerja Tinggi: Dari Docker Compose ke Produksi Bare Metal yang Optimal dengan Kubernetes
Dalam lanskap pengembangan aplikasi modern, penggunaan kontainerisasi dengan Docker telah menjadi praktik standar untuk memastikan konsistensi lingkungan dan portabilitas. Artikel ini akan memandu Anda melalui konfigurasi aplikasi Laravel Anda yang menggunakan FrankenPHP, Caddy, MariaDB, dan Redis, menganalisis file-file Dockerfile dan Docker Compose yang Anda sediakan, serta memberikan langkah-langkah konkret untuk mengoptimalkan deployment Anda ke lingkungan produksi bare metal yang stabil dan efisien menggunakan Kubernetes. Fokus utama adalah pada performa, keandalan, dan praktik terbaik.
1. Memahami Komponen Aplikasi Anda
Aplikasi Anda terdiri dari beberapa layanan utama yang diorkestrasi menggunakan Docker Compose:
f_laravel
: Aplikasi Laravel Anda yang berjalan di atas FrankenPHP (melalui Laravel Octane). FrankenPHP adalah application server PHP modern yang dirancang untuk kinerja tinggi, sangat cocok untuk Laravel Octane.caddy
: Web server yang berfungsi sebagai reverse proxy di depanf_laravel
. Caddy juga bertanggung jawab untuk melayani aset statis dan mengelola HTTPS secara otomatis.db
: Database MariaDB untuk penyimpanan data aplikasi Anda.redis
: In-memory data store yang digunakan untuk caching dan antrean (queue) oleh aplikasi Laravel Anda.
Mari kita bedah konfigurasi setiap komponen dan diskusikan area peningkatannya.
2. Analisis dan Perbaikan db.dockerfile
(Image Laravel FrankenPHP)
File db.dockerfile
adalah instruksi untuk membangun image Docker yang akan menjalankan aplikasi Laravel Anda dengan FrankenPHP.
# Menggunakan base image FrankenPHP PHP 8.3
FROM dunglas/frankenphp:latest
# Mengatur direktori kerja di dalam container
WORKDIR /app
# Menyalin executable Composer dari image Composer yang terpisah
COPY --from=composer:2.2 /usr/bin/composer /usr/bin/composer
# --- Dependensi dan Persiapan Esensial ---
RUN apt-get update && \
apt-get install -y \
zip \
libzip-dev \
curl \
iputils-ping \
default-mysql-client \
autoconf \
g++ \
make \
&& \
docker-php-ext-install zip pcntl pdo pdo_mysql sockets && \
pecl install redis && docker-php-ext-enable redis && \
apt-get purge -y --auto-remove autoconf g++ make && \
rm -rf /var/lib/apt/lists/*
Analisis:
Penggunaan
dunglas/frankenphp:latest
adalah pilihan yang solid karena menyediakan PHP dan FrankenPHP yang terintegrasi.Menyalin Composer dari image terpisah (
composer:2.2
) adalah praktik yang baik untuk memastikan Composer tersedia di image builder.Instalasi dependensi sistem dan ekstensi PHP (
zip
,pcntl
,pdo
,pdo_mysql
,sockets
,redis
) adalah langkah yang tepat untuk fungsionalitas Laravel.apt-get purge -y --auto-remove autoconf g++ make
adalah langkah penting untuk mengurangi ukuran image dengan menghapus alat build yang tidak lagi diperlukan setelah ekstensi dikompilasi.
Perbaikan & Standar Terbaik:
Multi-Stage Build (Sangat Direkomendasikan untuk Produksi): Untuk efisiensi dan keamanan, pisahkan proses build (instalasi dependensi Composer, kompilasi aset frontend) dari runtime. Ini menghasilkan image produksi yang jauh lebih kecil karena tidak menyertakan alat build yang tidak dibutuhkan di runtime.
Dockerfile# db.dockerfile (Revisi dengan Multi-Stage Build) # --- Stage 1: Builder --- FROM dunglas/frankenphp:latest AS builder WORKDIR /app # Menyalin executable Composer dari image Composer yang terpisah COPY --from=composer:2.2 /usr/bin/composer /usr/bin/composer # Install system dependencies needed for building extensions and Composer RUN apt-get update && \ apt-get install -y \ zip \ libzip-dev \ curl \ iputils-ping \ default-mysql-client \ autoconf \ g++ \ make \ && \ docker-php-ext-install zip pcntl pdo pdo_mysql sockets && \ pecl install redis && docker-php-ext-enable redis && \ # Tidak perlu purge di stage builder, karena image ini akan dibuang rm -rf /var/lib/apt/lists/* # Copy your application code COPY --chown=www-data:www-data . /app # Configure Composer environment ENV COMPOSER_PROCESS_TIMEOUT=600 \ COMPOSER_MEMORY_LIMIT=-1 # Install Composer dependencies RUN echo "--- Checking connectivity to Packagist ---" && \ curl -vvv --max-time 30 https://repo.packagist.org/packages.json || true && \ echo "--- Installing Composer dependencies ---" && \ composer install --no-interaction --prefer-dist --optimize-autoloader --verbose # Install Laravel Octane RUN echo "--- Installing Laravel Octane ---" && \ composer require laravel/octane --no-interaction --prefer-dist --verbose # Run Octane specific installation/optimization RUN composer dump-autoload && \ php artisan octane:install --server=frankenphp --force && \ php artisan optimize # Run optimize at build time for faster startup # --- Stage 2: Runtime --- FROM dunglas/frankenphp:latest WORKDIR /app # Copy only necessary runtime files from builder stage COPY --from=builder /app /app # Ensure correct permissions RUN chown -R www-data:www-data /app/storage /app/bootstrap/cache && \ chmod -R ug+rwx /app/storage /app/bootstrap/cache # Exposed port for FrankenPHP EXPOSE 8002 # Command to run the application CMD ["php", "artisan", "octane:start", "--host=0.0.0.0", "--port=8002", "--server=frankenphp", "--workers=auto"]
Mengapa ini lebih baik?
Ukuran Image Lebih Kecil: Image akhir hanya berisi runtime dan kode aplikasi, tanpa alat build seperti
gcc
,make
, atau bahkancomposer
. Ini mengurangi footprint, mempercepat pull, dan mengurangi permukaan serangan keamanan.Keamanan Lebih Baik: Dengan menghapus alat build, potensi kerentanan yang terkait dengan alat-alat tersebut juga dihilangkan dari image produksi.
Kinerja Startup:
php artisan optimize
dijalankan saat build, sehingga kontainer dimulai lebih cepat di runtime karena tidak perlu melakukan optimasi lagi.
Permissions: Pastikan direktori seperti
storage
danbootstrap/cache
memiliki izin tulis yang benar untuk userwww-data
di dalam kontainer. Ini sudah ditambahkan dalamRUN chown -R ...
di runtime stage.
3. Analisis dan Perbaikan Caddyfile
(Konfigurasi Caddy)
Caddyfile
mengatur bagaimana Caddy berfungsi sebagai reverse proxy dan melayani aplikasi Anda.
# Mengkonfigurasi Caddy untuk melayani domain lokal atau IP
# Ganti 'localhost' dengan domain Anda jika Anda memiliki satu (misalnya, 'yourdomain.com')
# Caddy akan secara otomatis menangani HTTPS untuk domain yang valid
:80 {
# Mengatur root dokumen ke direktori publik Laravel
root * /app/public
# Mengaktifkan kompresi Gzip untuk respons
encode gzip
# Mengaktifkan log akses
log {
output stdout
format json
}
# Menangani file statis secara langsung
file_server
# Meneruskan semua permintaan yang tidak cocok dengan file statis ke server Octane (FrankenPHP)
# 'f_laravel:8002' adalah nama layanan Docker Compose dan port yang didengarkan oleh FrankenPHP
reverse_proxy f_laravel:8002 {
# Mengatur header Host untuk diteruskan dengan benar
header_up Host {host}
# Mengatur header X-Forwarded-For untuk alamat IP klien
header_up X-Forwarded-For {remote_ip}
# Mengatur header X-Forwarded-Proto untuk protokol (HTTP/HTTPS)
header_up X-Forwarded-Proto {scheme}
}
# Jika ada error, tampilkan halaman error Laravel
handle_errors {
rewrite * /index.php
reverse_proxy f_laravel:8002
}
}
Analisis:
Konfigurasi ini sudah sangat baik untuk fungsionalitas dasar Caddy sebagai reverse proxy di depan FrankenPHP dan melayani aset statis.
Penggunaan
root * /app/public
danfile_server
memastikan Caddy melayani aset statis secara langsung, mengurangi beban pada FrankenPHP.reverse_proxy f_laravel:8002
dengan headerHost
,X-Forwarded-For
, danX-Forwarded-Proto
adalah standar untuk meneruskan request dengan benar ke backend.handle_errors
yang mengarahkan kembali keindex.php
adalah praktik umum untuk aplikasi PHP.
Perbaikan & Standar Terbaik:
HTTPS (Produksi): Untuk produksi, sangat disarankan untuk mengaktifkan HTTPS. Caddy memiliki fitur auto-HTTPS yang luar biasa. Cukup ganti
:80
dengan nama domain Anda (misalnyayourdomain.com
) dan Caddy akan secara otomatis mendapatkan dan memperbarui sertifikat Let's Encrypt.Code snippet# yourdomain.com atau IP_PUBLIK_ANDA { # Ganti ini di produksi :80 { # Tetap gunakan ini untuk development lokal atau pengujian HTTP # ... konfigurasi yang ada ... # Jika di produksi dan memiliki domain: # tls { # # Untuk Force HTTPS Redirect # redirect http://{host}{uri} # } }
Timeouts: Untuk stabilitas yang lebih baik, terutama dengan aplikasi yang mungkin memiliki request panjang, Anda bisa menambahkan timeout pada blok
reverse_proxy
.Code snippetreverse_proxy f_laravel:8002 { # ... header up ... transport http { read_timeout 60s # Contoh: Waktu maksimal menunggu respons dari backend write_timeout 60s # Contoh: Waktu maksimal untuk mengirim request ke backend dial_timeout 10s # Contoh: Waktu maksimal untuk membuat koneksi ke backend } }
4. Analisis dan Perbaikan caddy.dockerfile
(Image Caddy)
Ini adalah Dockerfile untuk membangun image Caddy kustom Anda.
# Menggunakan base image Caddy resmi
FROM caddy:2.7.5-alpine
# Mengatur direktori kerja di dalam container
WORKDIR /app
# Menyalin Caddyfile ke lokasi default Caddy
# Pastikan Caddyfile Anda bernama 'Caddyfile' dan berada di direktori yang sama dengan Dockerfile ini
COPY Caddyfile /etc/caddy/Caddyfile
# Menyalin direktori publik aplikasi Laravel.
# Ini diperlukan agar Caddy dapat melayani file statis secara langsung.
COPY public /app/public
# Mengekspos port default Caddy (HTTP)
EXPOSE 80
# Jika Anda mengaktifkan HTTPS, Caddy juga akan menggunakan port 443
EXPOSE 443
# Perintah default untuk menjalankan Caddy
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
Analisis:
Penggunaan
caddy:2.7.5-alpine
adalah standar yang baik.Penyalinan
Caddyfile
dan direktoripublic
sudah benar untuk memastikan Caddy memiliki semua yang dibutuhkan di dalam image.EXPOSE 80
danEXPOSE 443
adalah deklarasi yang benar untuk port yang akan diekspos.CMD
untuk menjalankan Caddy sudah tepat.
Perbaikan & Standar Terbaik:
Tidak ada perubahan signifikan yang diperlukan untuk
caddy.dockerfile
ini dari perspektif stabilitas dan efisiensi, karena sudah cukup optimal untuk tujuannya.
5. Analisis dan Perbaikan docker-compose.yml
(Orkestrasi Lokal)
File docker-compose.yml
adalah file orkestrasi Anda untuk lingkungan pengembangan.
version: '3.8'
services:
f_laravel:
image: image_f_laravel
container_name: f_laravel
build:
context: .
dockerfile: db.dockerfile
volumes:
- .:/app # <-- PERHATIKAN INI UNTUK PRODUKSI
- vendor_data:/app/vendor
env_file:
- .env
environment:
DB_HOST: db
REDIS_HOST: redis
networks:
- app_network
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
entrypoint: ["/bin/sh", "-c"]
command: >
"php artisan config:clear;
php artisan cache:clear;
php artisan route:clear;
php artisan view:clear;
php artisan optimize:clear;
php artisan key:generate;
php artisan storage:link;
php artisan migrate --force;
php artisan migrate;
php artisan optimize;
php artisan octane:start --host=0.0.0.0 --port=8002 --server=frankenphp --workers=auto;
tail -f /dev/null"
Analisis:
f_laravel
:volumes: - .:/app
: Ini adalah sangat baik untuk pengembangan karena memungkinkan hot-reloading kode. Namun, sangat tidak disarankan untuk produksi karena performa I/O bisa terganggu, tidak mendukung multi-replika, dan rentan terhadap perubahan kode yang tidak disengaja.command
: Perintah Artisan yang panjang ini dijalankan setiap kali kontainer dimulai. Ini sangat nyaman untuk development tetapi tidak efisien dan berpotensi tidak stabil untuk produksi.php artisan migrate
seharusnya hanya berjalan sekali per deployment.php artisan key:generate
juga hanya sekali.
caddy:
image: caddy:2.7.5-alpine
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./public:/app/public # <-- PERHATIKAN INI UNTUK PRODUKSI
- caddy_data:/data
networks:
- app_network
depends_on:
- f_laravel
Analisis:
volumes: - ./Caddyfile:/etc/caddy/Caddyfile
: Ini bagus untuk pengembangan agar Anda bisa mengubah Caddyfile tanpa rebuild image.volumes: - ./public:/app/public
: Sama sepertif_laravel
, ini baik untuk pengembangan (misalnya, jika aset frontend Anda berubah), tetapi tidak ideal untuk produksi karena alasan yang sama.
db:
image: mariadb:10.11
container_name: laravel_db
restart: unless-stopped
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' # <-- HINDARI INI DI PRODUKSI!
volumes:
- db_data:/var/lib/mysql
networks:
- app_network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
redis:
image: redis:7.2-alpine
container_name: laravel_redis
restart: unless-stopped
networks:
- app_network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 30
volumes:
vendor_data:
caddy_data:
db_data:
networks:
app_network:
driver: bridge
Analisis:
db
danredis
dikonfigurasi dengan baik untuk development dengan healthchecks dan named volumes untuk persistensi data.MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
: Ini adalah risiko keamanan besar dan harus dihindari sama sekali di produksi. Gunakan kata sandi yang kuat dan kelola sebagai secret.
Perbaikan & Standar Terbaik untuk Produksi (Transisi ke Kubernetes):
Ketika Anda beralih ke produksi bare metal dengan Kubernetes, docker-compose.yml
Anda tidak lagi digunakan secara langsung. Setiap layanan akan direpresentasikan sebagai objek Kubernetes (Deployment
, Service
, PersistentVolumeClaim
, ConfigMap
, Secret
).
Pengelolaan Kode Aplikasi:
Hentikan bind mounts untuk kode: Ganti
volumes: .:/app
(dif_laravel
) danvolumes: ./public:/app/public
(dicaddy
) dengan menyalin kode aplikasi secara langsung ke dalam image selama build Dockerfile (seperti yang disarankan dalam Multi-Stage Build di atas).Konsistensi Image: Pastikan image Docker Anda (build dari Dockerfile yang dioptimalkan) adalah sumber tunggal kebenaran untuk aplikasi Anda. Ini memastikan setiap kontainer yang di-deploy identik.
Manajemen Perintah Startup (Laravel Artisan):
php artisan migrate
: Ini harus dijalankan sebagai Kubernetes Job yang terpisah setelah deployment baru. Jobs dirancang untuk tugas satu kali yang harus berjalan hingga selesai, dan bisa dicoba ulang jika gagal. Ini mencegah migrasi berjalan berulang kali atau menyebabkan masalah jika kontainer sering di-restart.php artisan key:generate
: Kunci aplikasi harus dihasilkan sekali dan disimpan sebagai Kubernetes Secret, kemudian diinjeksikan ke kontainer Laravel sebagai variabel lingkungan. Tidak boleh dihasilkan setiap kali startup.Perintah Cache/Config/Route/View Clear: Ini bisa dijalankan sebagai bagian dari build Dockerfile jika Anda ingin image yang sudah bersih, atau sebagai post-deployment hook di Kubernetes jika Anda memiliki mekanisme untuk itu. Idealnya, image produksi sudah bersih.
php artisan optimize
: Seperti yang direkomendasikan, jalankan ini saat build Dockerfile untuk image produksi yang dioptimalkan.tail -f /dev/null
: Tidak lagi diperlukan jikaCMD
Anda adalah proses utama sepertiphp artisan octane:start
.
Manajemen Variabel Lingkungan & Rahasia (Secrets):
ConfigMap: Gunakan Kubernetes
ConfigMap
untuk variabel lingkungan non-sensitif (sepertiDB_HOST
,REDIS_HOST
,APP_ENV
).Secret: Gunakan Kubernetes
Secret
untuk variabel lingkungan yang sensitif (sepertiDB_PASSWORD
,APP_KEY
, kredensial API lainnya). Ini akan menggantikan.env
di produksi.MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
: HAPUS ini dari produksi. Gunakan kata sandi yang kuat dan injeksi melalui Kubernetes Secret.
Persistent Storage:
PersistentVolumeClaim (PVC): Di Kubernetes bare metal, named volumes (
vendor_data
,caddy_data
,db_data
) akan diganti denganPersistentVolumeClaim
yang terikat padaPersistentVolume
yang disediakan oleh StorageClass di klaster Anda (misalnya, OpenEBS untuk local storage atau Rook-Ceph untuk distributed storage). Ini memastikan data Anda persisten dan tersedia untuk Pod di node manapun.Direktori
public
untuk Upload: Jika aplikasi Anda memungkinkan upload file ke direktoripublic
, Anda perlu PVC terpisah untuk itu (sepertilaravel-public-pvc
yang saya sarankan sebelumnya), yang di-mount ke kedua kontainer (Laravel dan Caddy) jika Caddy juga perlu mengaksesnya. Jika tidak ada upload, cukup salinpublic
ke image.
Health Checks:
Pastikan health checks (
livenessProbe
danreadinessProbe
) yang tepat dikonfigurasi di Kubernetes Deployment untukf_laravel
,db
, danredis
. Ini membantu Kubernetes mengelola siklus hidup Pod dan memastikan hanya Pod yang sehat yang menerima traffic.
6. Transisi ke Kubernetes untuk Produksi Bare Metal yang Optimal
Meskipun Docker Compose sangat bagus untuk pengembangan dan single-host deployment sederhana, Kubernetes adalah standar de-facto untuk orkestrasi kontainer di produksi karena kapabilitas skalabilitas, self-healing, load balancing, dan manajemen sumber daya yang canggih.
Langkah-langkah Kunci untuk Transisi:
Instalasi Kubernetes di Bare Metal:
Container Runtime: Pastikan Docker Engine terinstal di setiap node bare metal Anda. Kubernetes akan menggunakannya sebagai container runtime.
Klaster Kubernetes: Instal klaster Kubernetes. Pilihan yang direkomendasikan untuk bare metal:
kubeadm
: Alat resmi dari Kubernetes untuk bootstrapping klaster. Memberi Anda kontrol penuh tetapi membutuhkan pemahaman yang mendalam.k3s
: Distro Kubernetes yang sangat ringan, dioptimalkan untuk edge dan sumber daya terbatas. Lebih mudah diinstal dan dikelola, sangat cocok untuk memulai.MicroK8s
: Kubernetes yang mudah diinstal untuk klaster kecil/pengembangan, dari Canonical.
Konfigurasi StorageClass:
Ini adalah perbedaan krusial dari Docker Compose. Di bare metal, Anda membutuhkan StorageClass untuk mengklaim
PersistentVolumeClaim
(PVC) Anda.Contoh Solusi StorageClass:
OpenEBS (Local PV): Jika Anda ingin memanfaatkan disk lokal di setiap node untuk persistensi data dan mengelola data aplikasi secara terpisah. Baik untuk database yang tidak memerlukan replikasi klaster Kubernetes (MariaDB Anda).
Rook-Ceph: Untuk solusi storage terdistribusi yang lebih canggih, cocok untuk klaster besar dan data yang sangat penting.
NFS Provider: Jika Anda memiliki server NFS terpusat.
Definisi Objek Kubernetes (YAML Manifests): Setiap layanan Anda akan dipecah menjadi objek Kubernetes yang terpisah:
Deployment (untuk
f_laravel
,caddy
,db
,redis
): Mendefinisikan state yang diinginkan (jumlah replika, image, resource requests/limits, probes).Optimalisasi CPU-Intensive: Untuk
f_laravel
(Laravel Octane), Anda akan mengaturresources.requests.cpu
danresources.limits.cpu
secara eksplisit untuk menjamin performa yang stabil. Misalnya,cpu: "2000m"
untuk 2 core danmemory: "2Gi"
untuk 2GB RAM dilimits
.
Service (untuk
f_laravel
,db
,redis
,caddy
): Mendefinisikan bagaimana Pod Anda dapat diakses.Untuk
db
danredis
, gunakantype: ClusterIP
(hanya dapat diakses dari dalam klaster).Untuk
f_laravel
, gunakantype: ClusterIP
karena Caddy akan menjadi satu-satunya yang berkomunikasi dengannya.Untuk
caddy
(akses eksternal):type: NodePort
: Solusi paling sederhana untuk bare metal. Akan mengekspos Caddy di port tertentu di setiap node (misalnya,http://<IP_NODE>:30080
).Ingress Controller
(Nginx Ingress Controller, Traefik, dll.) +Ingress Resource
: Pendekatan yang direkomendasikan untuk produksi. Ini menyediakan load balancing eksternal, routing berbasis nama host (misalnya,yourdomain.com
), SSL termination, dan features canggih lainnya. Caddy Service Anda akan tetapClusterIP
, dan Ingress akan mengarah ke Service Caddy.
ConfigMap (untuk
Caddyfile
, variabel.env
non-sensitif):Caddyfile
yang Anda definisikan akan menjadi entri di ConfigMap, yang kemudian di-mount sebagai file ke kontainer Caddy.Variabel lingkungan seperti
APP_ENV
,APP_URL
dari.env
Anda juga akan menjadi entri di ConfigMap dan diinjeksikan ke Pod Laravel.
Secret (untuk variabel
.env
sensitif):Kredensial database (
DB_USERNAME
,DB_PASSWORD
),APP_KEY
, dan rahasia lainnya harus disimpan sebagai Secret. Ini adalah cara yang aman untuk menangani informasi sensitif di Kubernetes.
PersistentVolumeClaim (PVC):
Buat PVC untuk
db_data
,vendor_data
,caddy_data
, danpublic
(jika dapat ditulis). Ini akan mengklaim ruang penyimpanan persisten dari StorageClass Anda.
Job (untuk
php artisan migrate
):Untuk
php artisan migrate
, buatlahJob
Kubernetes terpisah. Job ini akan menjalankan migrasi sekali dan keluar.
Monitoring dan Logging:
Implementasikan solusi monitoring (misalnya, Prometheus + Grafana) untuk memantau penggunaan CPU, memori, network, dan I/O dari node Kubernetes dan Pod Anda.
Siapkan sistem logging terpusat (misalnya, ELK Stack atau Loki + Grafana) untuk mengumpulkan log dari semua kontainer Anda.
Contoh Struktur YAML Manifests Kubernetes (Direkomendasikan)
Anda akan memiliki folder seperti k8s-manifests/
yang berisi file-file YAML terpisah:
k8s-manifests/
├── 01-configmaps-secrets.yaml # ConfigMaps dan Secrets Anda
├── 02-storage.yaml # PersistentVolumeClaims Anda
├── 03-db-deployment-service.yaml # Deployment dan Service untuk MariaDB
├── 04-redis-deployment-service.yaml # Deployment dan Service untuk Redis
├── 05-laravel-deployment-service.yaml # Deployment dan Service untuk Laravel FrankenPHP
├── 06-caddy-deployment-service.yaml # Deployment dan Service untuk Caddy
├── 07-ingress.yaml # (Opsional) Ingress Resource jika pakai Ingress Controller
└── 08-migrations-job.yaml # (Opsional) Job untuk php artisan migrate
Setiap file akan berisi satu atau lebih objek Kubernetes yang relevan. Dengan menjalankan kubectl apply -f k8s-manifests/
Anda akan mendeploy seluruh aplikasi Anda.
Kesimpulan
Transisi dari Docker Compose ke Kubernetes untuk produksi bare metal adalah langkah yang signifikan tetapi sangat berharga untuk mencapai sistem yang stabil, efisien, dan kompatibel di banyak environment. Dengan mengoptimalkan Dockerfile Anda (terutama dengan multi-stage builds), mengelola variabel lingkungan dan rahasia dengan ConfigMap/Secret, dan memanfaatkan kemampuan orkestrasi canggih Kubernetes untuk resource allocation, persistent storage, dan service management, Anda akan membangun platform yang kokoh untuk aplikasi Laravel berkinerja tinggi Anda. Ingatlah bahwa investasi waktu awal untuk mempelajari Kubernetes akan terbayar dengan peningkatan keandalan dan skalabilitas aplikasi Anda di masa mendatang.