Slide 1

Slide 1 text

Symfony Apps As Standalone Binaries The story of a successful experimentation

Slide 2

Slide 2 text

Kévin Dunglas: ➔ CEO @ Les-Tilleuls.coop ➔ FrankenPHP and API Platform creator ➔ Symfony Core Team ➔ PHP and Go contributor @dunglas

Slide 3

Slide 3 text

70+ API, Web and Cloud Experts ➔ Dev, consultancy and hosting ➔ 100% employee-owned co-op ✊ ➔ API Platform creators 🕷 ➔ Symfony backers 🎼 ➔ PHP Foundation advisory board 🐘 ➔ [email protected] 💌

Slide 4

Slide 4 text

Prerequisites to Deploy a Symfony App in Prod ➔ A web server (NGINX, Caddy, Apache…) ➔ A PHP executor PHP-FPM (most likely) ➔ Usually, some PHP extensions curl, pdo_*, gd, apcu... ➔ Usually, a database server PostgreSQL, MariaDB, MongoDB…

Slide 5

Slide 5 text

Deploying your Symfony App When your server(s) is ready, you need to: ➔ Get the latest stable version of app source code ➔ Install the dependencies of your project: composer install --no-dev -a

Slide 6

Slide 6 text

The Good Old Days of FTP 👴

Slide 7

Slide 7 text

FTP/SCP, Shared Hosting 👴 ➔ Easy (and usually cheap) ➔ No (or limited) control over ● PHP version ● Extensions ● Config ➔ Not possible to install custom extra services (Redis…)

Slide 8

Slide 8 text

Your Own Servers (or Computer) ➔ Full control over everything ➔ You are on your own for everything ● Initial setup ● Security ● Performance ● Upgrades…

Slide 9

Slide 9 text

Platforms as a Service

Slide 10

Slide 10 text

Platforms As a Service ➔ git push and done… ➔ … as long as your app is pretty standard ➔ The platform installs, maintains and optimizes the infrastructure (hardware and software) for you

Slide 11

Slide 11 text

Symfony & Docker

Slide 12

Slide 12 text

The Symfony Docker skeleton ➔ Skeleton with good defaults ➔ Full control over everything ➔ Extensible ➔ Same environment in dev, in your CI pipelines and in prod ➔ You still need servers ➔ Can be hard in prod (knowledge!)

Slide 13

Slide 13 text

Let’s Experiment!

Slide 14

Slide 14 text

Reminders: PHP ➔ PHP is an interpreted language (script) ➔ The CPU cannot execute directly a PHP script ➔ An interpreter is needed ➔ The official interpreter (php-src) is written in C ➔ The PHP interpreter doesn’t contain a (production-grade) web server

Slide 15

Slide 15 text

Reminders: dynamic vs static linking ➔ The PHP interpreter and its extensions depends on C and C++ libraries (ex: libcurl, OpenSSL, libsodium) ➔ These libraries can be linked with the interpreter dynamically or statically ➔ Dynamic linking: the library is a shared external binary (.so file on Linux) loaded at runtime by programs. Typical for PHP. ➔ Static linking: the library is embedded in the program binary. Hard to do for PHP. © Tatiana Fernández

Slide 16

Slide 16 text

Our Goals ➔ Distribute PHP apps as standalone binaries ➔ The binary must work without a local PHP or web server ➔ The end-user shouldn’t even know the app is written in PHP ➔ SO the binary must contain ● A web server ● The PHP executor ● The PHP code and the assets ● The vendors ➔ The binary must be statically compiled, with no external dependencies

Slide 17

Slide 17 text

Our Weapons

Slide 18

Slide 18 text

➔ Written in Go 😻 ● Can be compiled statically ● Can embed static C libraries, such as PHP ● Can embed arbitraries files, such as our app, assets and vendors ➔ Extensible with modules ➔ Prod ready ● HTTP/2, HTTP/3, Early Hints… ● Automatic HTTPS ⚔ Our Weapons: The Caddy Web Server

Slide 19

Slide 19 text

⚔ Our Weapons: FrankenPHP 1.0 🎉 New website, created by Laury Sorriaux.

Slide 20

Slide 20 text

➔ Standalone Go library ➔ Embed the official PHP executor in your Go programs ➔ New SAPI for Go net/http ➔ Caddy module using the library ➔ Unique features: ● Worker mode ⚡ ● 103 Early Hints ● Extensible in Go ⚔ Our Weapons: FrankenPHP

Slide 21

Slide 21 text

⚔ More About FrankenPHP

Slide 22

Slide 22 text

➔ Compile statically: ● PHP (CLI, FPM, libphp…) ● Its dependencies (pkgconfig…) ● Most PHP extensions (curl, gd, apcu, intl…) ● Most PHP extensions dependencies (libxml, libpng…) 🔁 ➔ CLI tool, written in PHP ➔ Entirely configurable ➔ Used by FrankenPHP, Native PHP, Laravel Laravel Herd… ⚔ Our Weapons: static-php-cli

Slide 23

Slide 23 text

⚔ Our Weapons: static-php-cli

Slide 24

Slide 24 text

⚔ Our Weapons: Go embed Package

Slide 25

Slide 25 text

Summary We’ll create a static binary containing: ➔ A web server (Caddy) ➔ PHP (and its dependencies) ➔ The extensions we need (and their dependencies) ➔ FrankenPHP ➔ Our PHP code ➔ The dependencies of our PHP code ➔ Our assets

Slide 26

Slide 26 text

I’ve Done The Wiring Work For You!

Slide 27

Slide 27 text

Let’s Try

Slide 28

Slide 28 text

Prepare your app $ echo APP_ENV=prod > .env.local $ echo APP_DEBUG=0 >> .env.local $ rm -Rf .git/, tests/ $ composer install --no-dev -a $ composer dump-env prod

Slide 29

Slide 29 text

$ git clone \ https://github.com/dunglas/frankenphp $ cd frankenphp $ EMBED=/path/to/my/sfapp \ ./build-static.sh # 🎉🎉🎉 $ cp dist/frankenphp-- my-app Build (Linux and Mac)!

Slide 30

Slide 30 text

Run Web server (HTTPS, HTTP/3…) $ ./my-app php-server --domain=example.com Worker mode (HTTPS, HTTP/3) $ ./my-app php-server -w public/index.php CLI $ ./my-app php-cli bin/console app:my-cmd

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

Ready-Made Dockerfile FROM dunglas/frankenphp:static-builder # Copy your app WORKDIR /go/src/app/dist/app COPY . . # Build the static binary, be sure to select only the PHP extensions you want WORKDIR /go/src/app/ RUN EMBED=dist/app/ \ PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \ ./build-static.sh

Slide 33

Slide 33 text

More Options Environment variables: ➔ PHP_VERSION: the PHP version to use (currently, 8.2 or 8.3) ➔ PHP_EXTENSIONS: PHP extensions to build (build only what you need to reduce the binary size) ➔ PHP_EXTENSIONS_LIB: extra libs (ex: libjpeg for GD) to build ➔ FRANKENPHP_VERSION: the FrankenPHP version to use

Slide 34

Slide 34 text

Any questions? Come at our booth! Thanks! frankenphp.dev @dunglas