Build Container Aplikasi Laravel dengan FrankenPHP

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

1FROM docker.io/oven/bun:1 AS asset-builder
2 
3COPY package.json bun.lockb /app/
4 
5WORKDIR /app
6 
7RUN bun install
8 
9COPY . .
10 
11RUN bun run build
12 
13FROM docker.io/serversideup/php:8.4-cli as vendor
14 
15COPY --chown=www-data:www-data . /var/www/html
16 
17RUN composer install --no-interaction --optimize-autoloader --ignore-platform-reqs --no-dev
18 
19FROM docker.io/dunglas/frankenphp:static-builder-musl-1.7.0 AS builder
20 
21ENV NO_COMPRESS=1
22 
23# Copy your app
24WORKDIR /go/src/app/dist/app
25 
26COPY . .
27 
28# Remove the tests and other unneeded files to save space
29# Alternatively, add these files to a .dockerignore file
30RUN rm -Rf tests/
31COPY --from=vendor /var/www/html /go/src/app/dist/app
32COPY --from=asset-builder /app/public/build /go/src/app/dist/app/public/build
33 
34# Build the static binary, be sure to select only the PHP extensions you want
35WORKDIR /go/src/app/
36 
37RUN EMBED=dist/app/ ./build-static.sh
38 
39FROM gcr.io/distroless/static-debian12
40 
41ARG build=dev
42 
43ENV BUILD $build
44 
45WORKDIR /app
46 
47COPY --from=builder /go/src/app/dist/frankenphp-linux-x86_64 blog
48 
49ENTRYPOINT ["/app/blog", "php-server"]

Penjelasan Multi-Stage build

Stage 1: Asset Builder

Stage ini menggunakan Bun untuk build frontend assets (CSS, Javascript):

Stage 2: PHP Dependencies

Stage ini berisi instalasi Composer dependencies, menggunakan base image dari serversideup:

Stage 3: Static Binary Build

Membuat static binary dengan FrankenPHP:

Stage 4: Final Runtime

Stage terakhir yang menghasilkan image production

Build Docker Image

Jalankan perintah berikut untuk build image:

1podman build --format=docker \
2 -t wayanjimmy/blog-10:latest .

Menjalankan Container

Setelah build selesai, pastikan container berjalan tanpa masalah:

1podman container run -p 8080:80 \
2 --env-file=./.env --rm wayanjimmy/blog-10:latest

Extract Static Binary

Jika ingin mendapatkan static binary-nya saja:

1podman create --name temp-container wayanjimmy/blog-10:latest
2podman cp temp-container:/app/blog ./blog-binary
3podman rm temp-container

Sekarang file blog-binary bisa dijalankan langsung:

1chmod +x blog-binary
2./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.