Build Container Aplikasi Laravel dengan FrankenPHP
- Apa itu FrankenPHP?
- Persiapan
- Membuat Multi-Stage Container file
- Penjelasan Multi-Stage build
- Build Docker Image
- Menjalankan Container
- Extract Static Binary
- Kesimpulan
#Apa itu FrankenPHP?
FrankenPHP adalah PHP server yang sebenarnya adalah sebuah modul dari Caddy web server. Karena Caddy ditulis dengan Go memungkinkan FrankenPHP menghadirkan fitur self-contained executable, yang mana aplikasi Laravel akan dibungkus dalam single binary untuk memuluskan proses Deployment.
#Persiapan
Pastikan project Laravel sudah siap, ditulisan ini saya menggunakan blog ini yang memang ditulis dengan Laravel, dengan catatan frontend asset di project blog ini di build dengan Bun.
#Membuat Multi-Stage Container file
FROM docker.io/oven/bun:1 AS asset-builderCOPY package.json bun.lockb /app/WORKDIR /appRUN bun installCOPY . .RUN bun run buildFROM docker.io/serversideup/php:8.4-cli as vendorCOPY --chown=www-data:www-data . /var/www/htmlRUN composer install --no-interaction --optimize-autoloader --ignore-platform-reqs --no-devFROM docker.io/dunglas/frankenphp:static-builder-musl-1.7.0 AS builderENV NO_COMPRESS=1# Copy your appWORKDIR /go/src/app/dist/appCOPY . .# Remove the tests and other unneeded files to save space# Alternatively, add these files to a .dockerignore fileRUN rm -Rf tests/COPY --from=vendor /var/www/html /go/src/app/dist/appCOPY --from=asset-builder /app/public/build /go/src/app/dist/app/public/build# Build the static binary, be sure to select only the PHP extensions you wantWORKDIR /go/src/app/RUN EMBED=dist/app/ ./build-static.shFROM gcr.io/distroless/static-debian12ARG build=devENV BUILD $buildWORKDIR /appCOPY --from=builder /go/src/app/dist/frankenphp-linux-x86_64 blogENTRYPOINT ["/app/blog", "php-server"]
#Penjelasan Multi-Stage build
#Stage 1: Asset Builder
Stage ini menggunakan Bun untuk build frontend assets (CSS, Javascript):
- Install dependencies dengan
bun install
- Build assets dengan
bun run build
- Hasil build akan di-copy ke stage selanjutnya
#Stage 2: PHP Dependencies
Stage ini berisi instalasi Composer dependencies, menggunakan base image dari serversideup:
- Install Composer dependencies dengan optimasi production
- Flag
--no-dev
untuk skip development dependencies - Flag
--optimize-autoloader
untuk performa lebih baik
#Stage 3: Static Binary Build
Membuat static binary dengan FrankenPHP:
- Menggunakan base image
dunglas/frankenphp:static-builder-musl-1.7.0
- Menggabungkan source code, Composer dependencies, dan frontend build assets
- Aktivasi variable
NO_COMPRESS
untuk menghindari proses kompression binary karena ini akan menambah waktu build container image - Menjalankan script
build-static.sh
dari Frankenphp untuk compile menjadi single executable
#Stage 4: Final Runtime
Stage terakhir yang menghasilkan image production
- Menggunakan base image
distroless/static-debian12
- Hanya berisi static binary hasil compile
#Build Docker Image
Jalankan perintah berikut untuk build image:
podman build --format=docker \ -t wayanjimmy/blog-10:latest .
#Menjalankan Container
Setelah build selesai, pastikan container berjalan tanpa masalah:
podman container run -p 8080:80 \ --env-file=./.env --rm wayanjimmy/blog-10:latest
#Extract Static Binary
Jika ingin mendapatkan static binary-nya saja:
podman create --name temp-container wayanjimmy/blog-10:latestpodman cp temp-container:/app/blog ./blog-binarypodman rm temp-container
Sekarang file blog-binary
bisa dijalankan langsung:
chmod +x blog-binary./blog-binary php-server
#Kesimpulan
Dengan menggunakan FrankenPHP dan multi-stage Container build, kita bisa mengubah aplikasi Laravel menjadi self-contained single binary. Ini akan memuluskan proses deployment, karena menghilangkan beberapa component yang harus dijalankan seperti nginx/apache dan php-fpm.
Mesti ukuran binary cukup besar (sekitar 199MB), namun kemudahan deployment yang didapat menurut saya cukup worth it. Approach ini sangat cocok untuk menyederhanakan komponen yang di deploy, dan seperti blog ini saya deploy ke server Fly.io.