2023-12-02 14:51:17 +01:00
# PHP Apps As Standalone Binaries
FrankenPHP has the ability to embed the source code and assets of PHP applications in a static, self-contained binary.
2024-07-09 16:13:55 +02:00
Thanks to this feature, PHP applications can be distributed as standalone binaries that include the application itself, the PHP interpreter, and Caddy, a production-level web server.
2023-12-02 14:51:17 +01:00
2024-02-27 17:21:48 +01:00
Learn more about this feature [in the presentation made by Kévin at SymfonyCon 2023 ](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/ ).
2023-12-08 15:53:37 +01:00
2024-04-29 17:42:18 +02:00
For embedding Laravel applications, [read this specific documentation entry ](laravel.md#laravel-apps-as-standalone-binaries ).
2023-12-02 14:51:17 +01:00
## Preparing Your App
Before creating the self-contained binary be sure that your app is ready for embedding.
2024-07-09 16:13:55 +02:00
For instance, you likely want to:
2023-12-02 14:51:17 +01:00
2025-04-22 17:16:57 +02:00
- Install the production dependencies of the app
- Dump the autoloader
- Enable the production mode of your application (if any)
- Strip unneeded files such as `.git` or tests to reduce the size of your final binary
2023-12-02 14:51:17 +01:00
For instance, for a Symfony app, you can use the following commands:
``` console
# Export the project to get rid of .git/, etc
mkdir $TMPDIR/my-prepared-app
git archive HEAD | tar -x -C $TMPDIR/my-prepared-app
cd $TMPDIR/my-prepared-app
# Set proper environment variables
echo APP_ENV=prod > .env.local
echo APP_DEBUG=0 >> .env.local
2024-04-29 17:42:18 +02:00
# Remove the tests and other unneeded files to save space
# Alternatively, add these files with the export-ignore attribute in your .gitattributes file
2023-12-02 14:51:17 +01:00
rm -Rf tests/
# Install the dependencies
composer install --ignore-platform-reqs --no-dev -a
# Optimize .env
composer dump-env prod
```
2024-07-09 16:13:55 +02:00
### Customizing the Configuration
To customize [the configuration ](config.md ), you can put a `Caddyfile` as well as a `php.ini` file
in the main directory of the app to be embedded (`$TMPDIR/my-prepared-app` in the previous example).
2023-12-02 14:51:17 +01:00
## Creating a Linux Binary
The easiest way to create a Linux binary is to use the Docker-based builder we provide.
2024-04-29 17:42:18 +02:00
1. Create a file named `static-build.Dockerfile` in the repository of your app:
2023-12-02 14:51:17 +01:00
2025-04-22 17:16:57 +02:00
```dockerfile
2025-11-07 10:27:37 +01:00
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder-gnu
# If you intend to run the binary on musl-libc systems, use static-builder-musl instead
2023-12-02 14:51:17 +01:00
2025-04-22 17:16:57 +02:00
# Copy your app
WORKDIR /go/src/app/dist/app
COPY . .
2023-12-02 14:51:17 +01:00
2025-04-22 17:16:57 +02:00
# Build the static binary
WORKDIR /go/src/app/
RUN EMBED=dist/app/ ./build-static.sh
` ``
2023-12-02 14:51:17 +01:00
2025-04-22 17:16:57 +02:00
> [!CAUTION]
>
> Some ` .dockerignore` files (e.g. default [Symfony Docker ` .dockerignore`](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))
> will ignore the ` vendor/` directory and ` .env` files. Be sure to adjust or remove the ` .dockerignore` file before the build.
2024-03-06 07:30:59 +01:00
2023-12-02 14:51:17 +01:00
2. Build:
2025-04-22 17:16:57 +02:00
` ``console
docker build -t static-app -f static-build.Dockerfile .
` ``
2023-12-02 14:51:17 +01:00
2024-02-27 17:21:48 +01:00
3. Extract the binary:
2023-12-02 14:51:17 +01:00
2025-04-22 17:16:57 +02:00
` ``console
docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp
` ``
2023-12-02 14:51:17 +01:00
The resulting binary is the file named ` my-app` in the current directory.
## Creating a Binary for Other OSes
If you don't want to use Docker, or want to build a macOS binary, use the shell script we provide:
` ``console
2025-07-01 16:29:55 +08:00
git clone https://github.com/php/frankenphp
2023-12-02 14:51:17 +01:00
cd frankenphp
2024-04-23 14:04:47 +02:00
EMBED=/path/to/your/app ./build-static.sh
2023-12-02 14:51:17 +01:00
` ``
The resulting binary is the file named ` frankenphp-<os>-<arch>` in the ` dist/` directory.
## Using The Binary
2023-12-13 22:34:37 +01:00
This is it! The ` my-app` file (or ` dist/frankenphp-<os>-<arch>` on other OSes) contains your self-contained app!
2023-12-02 14:51:17 +01:00
To start the web app run:
` ``console
./my-app php-server
` ``
If your app contains a [worker script](worker.md), start the worker with something like:
` ``console
./my-app php-server --worker public/index.php
` ``
2024-07-09 16:13:55 +02:00
To enable HTTPS (a Let's Encrypt certificate is automatically created), HTTP/2, and HTTP/3, specify the domain name to use:
2023-12-08 15:53:37 +01:00
` ``console
./my-app php-server --domain localhost
` ``
2023-12-02 14:51:17 +01:00
You can also run the PHP CLI scripts embedded in your binary:
` ``console
./my-app php-cli bin/console
` ``
2024-04-23 14:04:47 +02:00
## PHP Extensions
By default, the script will build extensions required by the ` composer.json` file of your project, if any.
If the ` composer.json` file doesn't exist, the default extensions are built, as documented in [the static builds entry](static.md).
To customize the extensions, use the ` PHP_EXTENSIONS` environment variable.
2023-12-02 14:51:17 +01:00
## Customizing The Build
[Read the static build documentation](static.md) to see how to customize the binary (extensions, PHP version...).
## Distributing The Binary
2024-02-27 17:21:48 +01:00
On Linux, the created binary is compressed using [UPX](https://upx.github.io).
2023-12-02 14:51:17 +01:00
2024-02-27 17:21:48 +01:00
On Mac, to reduce the size of the file before sending it, you can compress it.
2023-12-02 14:51:17 +01:00
We recommend ` xz`.