Dockerfile Generator for Laravel: dockerfile-laravel!

Hi again @ricardosawir ! It took a bit of time, but! I took a look at the topic you’ve mentioned above, “single static file deployment”, and can see that FrankenPHP really does offer this!

The idea is that we prep our app for binary transformation, then we run FrankenPHP’s ./build-static.sh script to create a Single, portable binary that contains the following:

  1. PHP interpreter
  2. Caddy Web server
  3. Our Laravel app

Then, once the buld-static.sh script has generated that binary, all that’s left is to run the generated binary!

The steps above are do-able via a Dockerfile! dockerfile-laravel already generates a Dockerfile for us prepped for “binary transformation” So all we have to do is install dockerfile-laravel, then run its generate command to generate the dockerfile: vendor/bin/dockerfile-laravel.

Afterwards, we’ll have to revise the Dockerfile it generated to include and run Frankenphp’s build-static.sh script to build the single file binary of our app. So, in our Dockerfile, after the line RUN rsync -ar /var/www/html/public-npm/ /var/www/html/public/..., include a new build stage with frankenphp’s static-builder:

# OUR NEW and last build stage!
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder as builder

# Copy our app found in the previous "base" stage
WORKDIR /go/src/app/dist/app
COPY --from=base /var/www/html .

# Build the static binary, be sure to select only the PHP extensions you want
# ALSO! please set the FRANKENPHP_VERSION to the latest one
WORKDIR /go/src/app/
RUN EMBED=dist/app/ \
    FRANKENPHP_VERSION=1.1.2 \
    ./build-static.sh

# EXPOSE port
EXPOSE 80

ENTRYPOINT ["dist/frankenphp-linux-x86_64", "php-server"]

Notice 2 things here!

  1. We copy our prepped app from the base stage /var/www/html to our Frankenphp build stage “builder”.
  2. I’ve added an ENTRYPOINT entry. That’s basically running the generated binary “frankenphp-linux-x86_64” with the php-server command

With that, you can build the Dockerfile into an image with

docker build -t my-laravel-binary-app .

And run it locally with

docker run -p 80:80 my-laravel-binary-app

You can finally visit your application at 127.0.0.1:80!

Test it out if it works, and let me know if there’s anything I missed! I’ll try to add this as a beta feature in dockerfile-laravel, so watch out for that too!

NOTE!
In an earlier version of my answer, I incorrectly used the following syntax when building the binary:

RUN ./dist/frankenphp-linux-x86_64 version \
    export FRANKENPHP_VERSION=1.1.2 \
    EMBED=dist/app/ \
    ./build-static.sh

This however does not embed the app at all. So, how did I verify that new syntax embedded the app while the old one didn’t? These were the telltale signs:

  1. Building the Dockerfile into an image using the correct syntax takes time to build the image, since it’s embedding the whole app I added for EMBED
  2. Running the generated binary in the container using the correct syntax actually now logs( unlike the container that used the old incorrect syntax I mentioned above( under NOTE ), which did not log that path at all ):
embedded PHP app 📦     {"path": "/tmp/frankenphp_a204c16a3cc7597030296b259d908317  app.tar"}
  1. On the container containing the correct syntax, running the generated binary does not require the presence of the Laravel app directory found in /go/src/app/dist/app. The directory can be removed and the binary will still serve the application, unlike in a container containing the incorrect syntax, which would throw a 404 page not found if the directory was removed.