FrankenPHP: the modern PHP app server (original) (raw)
Contributing
# Compiling PHP
# With Docker (Linux)
Build the dev Docker image:
docker build -t frankenphp-dev -f dev.Dockerfile .
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -p 443:443/udp -v $PWD:/go/src/app -it frankenphp-dev
The image contains the usual development tools (Go, GDB, Valgrind, Neovim…) and uses the following php setting locations
- php.ini:
/etc/frankenphp/php.iniA php.ini file with development presets is provided by default. - additional configuration files:
/etc/frankenphp/php.d/*.ini - php extensions:
/usr/lib/frankenphp/modules/
If your Docker version is lower than 23.0, the build will fail due to dockerignore pattern issue. Add directories to .dockerignore.
!testdata/*.php
!testdata/*.txt
+!caddy
+!internal
# Without Docker (Linux and macOS)
Follow the instructions to compile from sources and pass the --debug configuration flag.
# Running the test suite
go test -tags watcher -race -v ./...
# Caddy module
Build Caddy with the FrankenPHP Caddy module:
cd caddy/frankenphp/
go build -tags watcher,brotli,nobadger,nomysql,nopgx
cd ../../
Run the Caddy with the FrankenPHP Caddy module:
cd testdata/
../caddy/frankenphp/frankenphp run
The server is listening on 127.0.0.1:80:
Note
if you are using Docker, you will have to either bind container port 80 or execute from inside the container
curl -vk http://127.0.0.1/phpinfo.php
# Minimal test server
Build the minimal test server:
cd internal/testserver/
go build
cd ../../
Run the test server:
cd testdata/
../internal/testserver/testserver
The server is listening on 127.0.0.1:8080:
curl -v http://127.0.0.1:8080/phpinfo.php
# Building Docker Images Locally
Print bake plan:
docker buildx bake -f docker-bake.hcl --print
Build FrankenPHP images for amd64 locally:
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"
Build FrankenPHP images for arm64 locally:
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"
Build FrankenPHP images from scratch for arm64 & amd64 and push to Docker Hub:
docker buildx bake -f docker-bake.hcl --pull --no-cache --push
# Debugging Segmentation Faults With Static Builds
- Download the debug version of the FrankenPHP binary from GitHub or create your custom static build including debug symbols:
docker buildx bake \
--load \
--set static-builder.args.DEBUG_SYMBOLS=1 \
--set "static-builder.platform=linux/amd64" \
static-builder
docker cp <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>d</mi><mi>o</mi><mi>c</mi><mi>k</mi><mi>e</mi><mi>r</mi><mi>c</mi><mi>r</mi><mi>e</mi><mi>a</mi><mi>t</mi><mi>e</mi><mo>−</mo><mo>−</mo><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><mi>s</mi><mi>t</mi><mi>a</mi><mi>t</mi><mi>i</mi><mi>c</mi><mo>−</mo><mi>b</mi><mi>u</mi><mi>i</mi><mi>l</mi><mi>d</mi><mi>e</mi><mi>r</mi><mo>−</mo><mi>m</mi><mi>u</mi><mi>s</mi><mi>l</mi><mi>d</mi><mi>u</mi><mi>n</mi><mi>g</mi><mi>l</mi><mi>a</mi><mi>s</mi><mi mathvariant="normal">/</mi><mi>f</mi><mi>r</mi><mi>a</mi><mi>n</mi><mi>k</mi><mi>e</mi><mi>n</mi><mi>p</mi><mi>h</mi><mi>p</mi><mo>:</mo><mi>s</mi><mi>t</mi><mi>a</mi><mi>t</mi><mi>i</mi><mi>c</mi><mo>−</mo><mi>b</mi><mi>u</mi><mi>i</mi><mi>l</mi><mi>d</mi><mi>e</mi><mi>r</mi><mo>−</mo><mi>m</mi><mi>u</mi><mi>s</mi><mi>l</mi><mo stretchy="false">)</mo><mo>:</mo><mi mathvariant="normal">/</mi><mi>g</mi><mi>o</mi><mi mathvariant="normal">/</mi><mi>s</mi><mi>r</mi><mi>c</mi><mi mathvariant="normal">/</mi><mi>a</mi><mi>p</mi><mi>p</mi><mi mathvariant="normal">/</mi><mi>d</mi><mi>i</mi><mi>s</mi><mi>t</mi><mi mathvariant="normal">/</mi><mi>f</mi><mi>r</mi><mi>a</mi><mi>n</mi><mi>k</mi><mi>e</mi><mi>n</mi><mi>p</mi><mi>h</mi><mi>p</mi><mo>−</mo><mi>l</mi><mi>i</mi><mi>n</mi><mi>u</mi><mi>x</mi><mo>−</mo></mrow><annotation encoding="application/x-tex">(docker create --name static-builder-musl dunglas/frankenphp:static-builder-musl):/go/src/app/dist/frankenphp-linux-</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">oc</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal">ercre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7429em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">es</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">u</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">u</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">d</span><span class="mord mathnormal">u</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">a</span><span class="mord mathnormal">s</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.03148em;">ank</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mord mathnormal">h</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7429em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">u</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">u</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">o</span><span class="mord">/</span><span class="mord mathnormal">src</span><span class="mord">/</span><span class="mord mathnormal">a</span><span class="mord mathnormal">pp</span><span class="mord">/</span><span class="mord mathnormal">d</span><span class="mord mathnormal">i</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.03148em;">ank</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mord mathnormal">h</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">in</span><span class="mord mathnormal">ux</span><span class="mord">−</span></span></span></span>(uname -m) frankenphp - Replace your current version of
frankenphpby the debug FrankenPHP executable - Start FrankenPHP as usual (alternatively, you can directly start FrankenPHP with GDB:
gdb --args frankenphp run) - Attach to the process with GDB:
gdb -p `pidof frankenphp` - If necessary, type
continuein the GDB shell - Make FrankenPHP crash
- Type
btin the GDB shell - Copy the output
# Debugging Segmentation Faults in GitHub Actions
- Open
.github/workflows/tests.yml - Enable PHP debug symbols
- uses: shivammathur/setup-php@v2
# ...
env:
phpts: ts
+ debug: true - Enable
tmateto connect to the container
- name: Set CGO flags
run: echo "CGO_CFLAGS=$(php-config --includes)" >> "$GITHUB_ENV"
+ - run: |
+ sudo apt install gdb
+ mkdir -p /home/runner/.config/gdb/
+ printf "set auto-load safe-path /\nhandle SIG34 nostop noprint pass" > /home/runner/.config/gdb/gdbinit
+ - uses: mxschmitt/action-tmate@v3 - Connect to the container
- Open
frankenphp.go - Enable
cgosymbolizer
- //_ "github.com/ianlancetaylor/cgosymbolizer"
+ _ "github.com/ianlancetaylor/cgosymbolizer" - Download the module:
go get - In the container, you can use GDB and the like:
go test -tags watcher -c -ldflags=-w
gdb --args frankenphp.test -test.run ^MyTest$ - When the bug is fixed, revert all these changes
# Misc Dev Resources
- PHP embedding in uWSGI
- PHP embedding in NGINX Unit
- PHP embedding in Go (go-php)
- PHP embedding in Go (GoEmPHP)
- PHP embedding in C++
- Extending and Embedding PHP by Sara Golemon
- What the heck is TSRMLS_CC, anyway?
- SDL bindings
# Docker-Related Resources
# Useful Command
apk add strace util-linux gdb
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
# Translating the Documentation
To translate the documentation and the site in a new language, follow these steps:
- Create a new directory named with the language’s 2-character ISO code in this repository’s
docs/directory - Copy all the
.mdfiles in the root of thedocs/directory into the new directory (always use the English version as source for translation, as it’s always up to date) - Copy the
README.mdandCONTRIBUTING.mdfiles from the root directory to the new directory - Translate the content of the files, but don’t change the filenames, also don’t translate strings starting with
> [!(it’s special markup for GitHub) - Create a Pull Request with the translations
- In the site repository, copy and translate the translation files in the
content/,data/andi18n/directories - Translate the values in the created YAML file
- Open a Pull Request on the site repository Edit this page