Docker One-Liner Compiles PHP to Native Binaries: Zero-Dependency Go-Style Distribution

This guide shows how to use TypePHP's Docker images to compile PHP code into standalone native Linux binaries without installing C++ or PHP toolchains locally, covering the compilation workflow, a common linker error caused by directory name conflicts, and advanced options like static compilation for scratch containers.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
Docker One-Liner Compiles PHP to Native Binaries: Zero-Dependency Go-Style Distribution

Introduction

Go's ability to produce a single, dependency-free native binary makes deployment trivial. Traditional PHP deployment, by contrast, requires a runtime, extensions, and code directories, leading to environment inconsistencies. TypePHP, an open-source Ahead-of-Time (AOT) compiler from the Swoole team, translates PHP directly into native machine code, giving PHP Go-like startup speed and single-file distribution. However, setting up the local C++17, PHP 8.5 ZTS/Embed, and GCC/Clang toolchain is a significant barrier. This article demonstrates how to bypass that setup entirely using pre-built Docker images.

Quick Start

Step 1: Prepare the PHP Entry File

Create main.php in your working directory. The entry point must be a function main(): int and use printf() for standard output:

declare(strict_types=1);

function main(): int {
    printf("Hello World from TypePHP Docker AOT!
");
    return 0;
}

Step 2: One-Line Compilation Command

Run the appropriate Docker command for your shell. The command mounts the current directory to /app inside the container and uses the tinywan/typephp-linux-x64:v0.7.0 image.

Windows PowerShell:

docker run --rm -v "${PWD}:/app" tinywan/typephp-linux-x64:v0.7.0

Linux / macOS / Git Bash:

docker run --rm -v "$(pwd):/app" tinywan/typephp-linux-x64:v0.7.0

Windows CMD:

docker run --rm -v "%cd%:/app" tinywan/typephp-linux-x64:v0.7.0

The container automatically detects the environment, transpiles PHP to C++, and compiles with GCC. The terminal streams the full build log, for example:

[TypePHP] Working directory: /app
[TypePHP] Detected PHP entrypoint: main.php
[TypePHP] Auto-generating project.yml for app...
[TypePHP] Generated project.yml:
name: app
bin: app.bin
sources:
- main.php
----------------------------------------
[TypePHP] Starting AOT compilation via tpc...
Initialized platform/backend: Linux + GCC (g++)
prepare: main.php
prepare completed: 1 source files in total
convert: main.php
generate arginfo file: main.php
[pch] built: opt/typephp/vendor/swoole/typephp/build/cache/pch/31e80de1e5c0ecccc9195c7b/typephp_pch.hpp.gch
Starting parallel compilation with 4 jobs for 6 files
Compiling [████████████████████████████████] 100% (6/6)
Successfully compiled 6 files
g++ '@./app.rsp' -o 'app.bin' -L '/opt/typephp/vendor/swoole/phpx/lib' -L '/usr/lib' -lphpx -lphp -lgmp -lgmpxx -lmpfr -lstdc++
[TypePHP] Build successful: app.bin

Within seconds, a native Linux ELF binary app.bin appears in the current directory.

Step 3: Run the Compiled Binary

The resulting app.bin is a standalone Linux executable. Verify it by running it inside the same Docker image:

docker run --rm -v "${PWD}:/app" tinywan/typephp-linux-x64:v0.7.0 ./app.bin

Output:

Hello World from TypePHP Docker AOT!

Troubleshooting: Linker Error "Is a directory"

Error Phenomenon

The linker fails with:

g++ '@./app.rsp' -o 'app' -L '/opt/typephp/vendor/swoole/phpx/lib' -L '/usr/lib' -lphpx -lphp ...
/usr/bin/ld: cannot open output file app: Is a directory
collect2: error: ld returned 1 exit status

Root Cause Analysis

Many PHP projects have an app/ directory for business logic. When project.yml sets name: app, the linker defaults the output executable to ./app. Because a directory with that name already exists, the linker cannot create a regular file, producing the "Is a directory" error.

Solution

Explicitly set the bin field in project.yml to a filename that does not clash with an existing directory:

name: app
bin: app.bin  # Explicitly specify binary name (e.g., server, demo)
sources:
- app/index.php

Re-run the compilation command; the binary will be generated successfully.

Advanced Usage

1. Compile a Single Script

If the directory contains multiple PHP files, specify the target script as an argument to the Docker command:

docker run --rm -v "${PWD}:/app" tinywan/typephp-linux-x64:v0.7.0 your_script.php

2. Fully Static, Single-File Binary (~6 MB)

To run on any Linux distribution or inside a FROM scratch container without glibc dependencies, switch to the static image based on Alpine/musl:

docker run --rm -v "${PWD}:/app" tinywan/typephp-linux-x64-static:v0.7.0

This produces a completely self-contained binary suitable for production distribution and minimal container deployment.

Docker Image Reference

Dynamic Compilation (Ubuntu / glibc) : tinywan/typephp-linux-x64:v0.7.0 — General development, local testing

Fully Static Single-File (Alpine / musl) : tinywan/typephp-linux-x64-static:v0.7.0 — Production distribution, cross-distro execution, scratch image deployment

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Dockerstatic linkingTypePHPnative binaryproject.ymlGo-style deploymentlinker errorPHP AOT compilation
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.