Dockerfile Generator for Laravel: dockerfile-laravel!

We want Fly.io to be the best place to deploy Laravel applications in, including all other external apps needed to make a Laravel application whole.

This is why the Laravel team at Fly.io has been making efforts to create repositories and packages that help in making Laravel applications ready for live action. Take for example the fly-apps/laravel-docker repository which provides a robust base Docker image for dockerizing Laravel applications. Then of course the fly-apps/fly-laravel package: for deploying your apps live. Just run it’s launch and deploy commands to go live with your Laravel app and necessary external applications (db, cache, storage ) in the Fly.io platform!

Enter dockerfile-laravel!

This time around, we created a new cli-package, dockerfile-laravel, geared towards dockerizing Laravel apps on top of the base docker image created from laravel-docker. With just one command:

dockerfile-laravel generate

dependencies required by your Laravel app will be scanned for and detected, and a Dockerfile tailored to your project generated.

It’s main goal is to detect different Laravel versions, packages, and dependency combinations, and create Dockerfiles tailored to successfully running these combinations. It’s at it’s earliest stages, and currently provides support for both Laravel 10 and 11 versions. And, it’s going to continue supporting newer versions in the future.

It’s also going to be used by flyctl in a near release to generate the Dockerfile used in deploying Laravel apps to Fly.io. That’s right! You can run it to generate Docker related files for your local Laravel container setup, and live server setup!

Ultimately:
It’s installable from packagist, and it’s repository is available publicly, with a special section on how to locally run this package. And yes, that’s where you, the Laravel Fly.io-ers community comes in!

Do test the package out, and submit any features/PR’s/issues you can.

Overtime more features can be requested, and reviewed, added, and maintained by the Laravel Fly team. Until such time dockerfile-laravel can run to successfully dockerize any Laravel application, and, ultimately, provide a package the Laravel community can turn to generating Dockerfiles for their Laravel applications, no matter how diverse their app set up be.

It’s exciting isn’t it? I am excited for this, and I hope you at the Laravel Fly community are too!

5 Likes

any plans on using frankenphp?

1 Like

Hi @ricardosawir!

Of course! There’s a flag you can pass on the generate command to create a Dockerfile that uses Octane - FrankenPHP. Simply run the command including the flag likeso:

vendor/bin/dockerfile-laravel generate --octane=frankenphp

And that should include Frankenphp in the Dockerfile configuration.

how about single static file deployment? Is it possible? Since from what I read frankenphp offers this, however have little idea how this could be implemented within docker

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.

Also, feast your eyes! This PR contains support for embedding a Laravel app into a FrankenPHP standalone binary! Works when deployed on Fly.io as well!

NOTES:

  1. The important Dockerfile code snippet needed to embed an app using FrankenPHP is here.

  2. Then of course a flag is required to be passed to signal that we want a FrankenPHP binary to be generated.

Thank you for suggesting this feature @ricardosawir! It will be included it in the new release of dockerfile-laravel.