---
title: "Build Container Aplikasi Laravel dengan FrankenPHP"
description: "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 a..."
publishedAt: 2025-06-25
locale: id
urlSlug: laravel-frankenphp-dalam-container
isDraft: false
defaultLocale: en
---
[TOC]

## Apa itu FrankenPHP?

[FrankenPHP](https://frankenphp.dev/) 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](https://gitlab.com/jimboylabs/blog-10) yang memang ditulis dengan Laravel, dengan catatan frontend asset di project blog ini di build dengan [Bun](https://github.com/oven-sh/bun).

## Membuat Multi-Stage Container file

```dockerfile
FROM docker.io/oven/bun:1 AS asset-builder

COPY package.json bun.lockb /app/

WORKDIR /app

RUN bun install

COPY . .

RUN bun run build

FROM docker.io/serversideup/php:8.4-cli as vendor

COPY --chown=www-data:www-data . /var/www/html

RUN composer install --no-interaction --optimize-autoloader --ignore-platform-reqs --no-dev

FROM docker.io/dunglas/frankenphp:static-builder-musl-1.7.0 AS builder

ENV NO_COMPRESS=1

# Copy your app
WORKDIR /go/src/app/dist/app

COPY . .

# Remove the tests and other unneeded files to save space
# Alternatively, add these files to a .dockerignore file
RUN rm -Rf tests/
COPY --from=vendor /var/www/html /go/src/app/dist/app
COPY --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 want
WORKDIR /go/src/app/

RUN EMBED=dist/app/ ./build-static.sh

FROM gcr.io/distroless/static-debian12

ARG build=dev

ENV BUILD $build

WORKDIR /app

COPY --from=builder /go/src/app/dist/frankenphp-linux-x86_64 blog

ENTRYPOINT ["/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](https://github.com/serversideup/docker-php):
- 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:

```bash
podman build --format=docker \
    -t wayanjimmy/blog-10:latest .
```

## Menjalankan Container

Setelah build selesai, pastikan container berjalan tanpa masalah:

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

## Extract Static Binary

Jika ingin mendapatkan static binary-nya saja:

```bash
podman create --name temp-container wayanjimmy/blog-10:latest
podman cp temp-container:/app/blog ./blog-binary
podman rm temp-container
```

Sekarang file `blog-binary` bisa dijalankan langsung:

```bash
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](https://fly.io/).
