Sign inSign up

diolektor/tokio_php

By diolektor

•Updated 8 months ago

Image
Web servers
0

8.2K

diolektor/tokio_php repository overview

⁠tokio_php

Beta — This project is experimental. The concept is being tested and validated. API and features may change. Not recommended for production use.

Feedback welcome: GitHub Issues⁠

High-performance async PHP server written in Rust. Uses Tokio for async I/O and php-embed SAPI for PHP execution.

Supported Architectures: linux/amd64, linux/arm64

⁠Features

  • HTTP/1.1 & HTTP/2 - Full protocol support with automatic detection
  • HTTPS/TLS 1.3 - Secure connections with ALPN negotiation
  • Worker Pool - Multi-threaded PHP execution with configurable workers
  • OPcache & JIT - PHP 8.4/8.5 with tracing JIT enabled
  • Brotli Compression - Automatic response compression
  • Rate Limiting - Per-IP request throttling
  • Distributed Tracing - W3C Trace Context support
  • Graceful Shutdown - Connection draining for zero-downtime deployments
  • Custom Error Pages - HTML error pages for 4xx/5xx responses
  • Prometheus Metrics - Built-in /health and /metrics endpoints

⁠Quick Start

# Pull the image
docker pull diolektor/tokio_php:php8.4-alpine3.23

# Run with default settings
docker run -d -p 8080:8080 -v $(pwd)/www:/var/www/html diolektor/tokio_php:php8.4-alpine3.23

# Run with custom configuration
docker run -d -p 8080:8080 \
  -e PHP_WORKERS=8 \
  -e INDEX_FILE=index.php \
  -v $(pwd)/www:/var/www/html \
  diolektor/tokio_php:php8.4-alpine3.23

⁠Available Tags

All tags are multi-arch (amd64 + arm64).

TagPHPAlpine
latest8.53.23
php8.58.53.23
php8.48.43.23
php8.5-alpine3.238.53.23
php8.4-alpine3.238.43.23

⁠Environment Variables

⁠Server Configuration
VariableDefaultDescription
LISTEN_ADDR0.0.0.0:8080Server bind address and port
DOCUMENT_ROOT/var/www/htmlWeb root directory
INDEX_FILE(empty)Single entry point file (e.g., index.php for Laravel/Symfony)
INTERNAL_ADDR(empty)Internal server address for /health and /metrics (e.g., 0.0.0.0:9090)
⁠Worker Pool
VariableDefaultDescription
PHP_WORKERS0Number of PHP worker threads. 0 = auto-detect (CPU cores)
QUEUE_CAPACITY0Max pending requests in queue. 0 = workers × 100
⁠TLS/HTTPS
VariableDefaultDescription
TLS_CERT(empty)Path to TLS certificate file (PEM format)
TLS_KEY(empty)Path to TLS private key file (PEM format)
⁠Features
VariableDefaultDescription
ERROR_PAGES_DIR(empty)Directory with custom HTML error pages (e.g., 404.html, 500.html)
STATIC_CACHE_TTL1dCache-Control max-age for static files. Values: off, 30s, 2m, 1h, 1d, 1w, 1y
REQUEST_TIMEOUT2mRequest timeout. Values: 30s, 2m, 5m, off. Returns 504 on timeout
DRAIN_TIMEOUT_SECS30Graceful shutdown timeout in seconds
⁠Rate Limiting
VariableDefaultDescription
RATE_LIMIT0Max requests per IP per window. 0 = disabled
RATE_WINDOW60Rate limit window in seconds
⁠Logging & Debugging
VariableDefaultDescription
RUST_LOGtokio_php=infoLog level: error, warn, info, debug, trace
ACCESS_LOG0Enable access logging. 1 = enabled
PROFILE0Enable request profiling. 1 = enabled (requires X-Profile: 1 header)
⁠Executor Mode
VariableDefaultDescription
USE_STUB0Stub mode (no PHP execution, for benchmarks). 1 = enabled
USE_EXT1Use FFI extension for superglobals (recommended, 2x faster). 0 = legacy mode

⁠Usage Examples

⁠Laravel / Symfony
docker run -d -p 8080:8080 \
  -e INDEX_FILE=index.php \
  -e DOCUMENT_ROOT=/var/www/html/public \
  -v $(pwd):/var/www/html \
  diolektor/tokio_php:php8.4-alpine3.23
⁠Production with Metrics
docker run -d -p 8080:8080 -p 9090:9090 \
  -e PHP_WORKERS=16 \
  -e QUEUE_CAPACITY=1000 \
  -e INTERNAL_ADDR=0.0.0.0:9090 \
  -e DRAIN_TIMEOUT_SECS=60 \
  -v $(pwd)/www:/var/www/html \
  diolektor/tokio_php:php8.4-alpine3.23
⁠With HTTPS
docker run -d -p 8443:8443 \
  -e LISTEN_ADDR=0.0.0.0:8443 \
  -e TLS_CERT=/certs/cert.pem \
  -e TLS_KEY=/certs/key.pem \
  -v $(pwd)/www:/var/www/html \
  -v $(pwd)/certs:/certs:ro \
  diolektor/tokio_php:php8.4-alpine3.23
⁠With Rate Limiting
docker run -d -p 8080:8080 \
  -e RATE_LIMIT=100 \
  -e RATE_WINDOW=60 \
  -v $(pwd)/www:/var/www/html \
  diolektor/tokio_php:php8.4-alpine3.23
⁠Custom Error Pages
docker run -d -p 8080:8080 \
  -e ERROR_PAGES_DIR=/var/www/html/errors \
  -v $(pwd)/www:/var/www/html \
  diolektor/tokio_php:php8.4-alpine3.23

Create error pages: errors/404.html, errors/500.html, errors/503.html

⁠Health Check & Metrics

Enable internal server with INTERNAL_ADDR:

# Health check
curl http://localhost:9090/health
{"status":"ok","timestamp":1703361234,"active_connections":5}

# Prometheus metrics
curl http://localhost:9090/metrics
⁠Available Metrics
  • tokio_php_uptime_seconds - Server uptime
  • tokio_php_requests_per_second - Average RPS
  • tokio_php_response_time_avg_seconds - Average response time
  • tokio_php_active_connections - Current connections
  • tokio_php_pending_requests - Queue size
  • tokio_php_requests_total{method} - Requests by HTTP method
  • tokio_php_responses_total{status} - Responses by status code
  • node_load1, node_load5, node_load15 - System load averages
  • node_memory_* - Memory statistics

⁠Profiling

Enable profiling and send requests with X-Profile: 1 header:

docker run -d -p 8080:8080 -e PROFILE=1 ...

curl -H "X-Profile: 1" http://localhost:8080/index.php -I

Response headers include timing data:

  • X-Profile-Total-Us - Total request time (microseconds)
  • X-Profile-Queue-Us - Worker queue wait time
  • X-Profile-Script-Us - PHP script execution time
  • X-Profile-TLS-Handshake-Us - TLS handshake time (HTTPS only)

⁠Kubernetes

apiVersion: v1
kind: Pod
spec:
  terminationGracePeriodSeconds: 35
  containers:
    - name: tokio-php
      image: diolektor/tokio_php:php8.4-alpine3.23
      ports:
        - containerPort: 8080
        - containerPort: 9090
      env:
        - name: PHP_WORKERS
          value: "8"
        - name: INTERNAL_ADDR
          value: "0.0.0.0:9090"
        - name: DRAIN_TIMEOUT_SECS
          value: "30"
      livenessProbe:
        httpGet:
          path: /health
          port: 9090
      readinessProbe:
        httpGet:
          path: /health
          port: 9090
      lifecycle:
        preStop:
          exec:
            command: ["sleep", "5"]

⁠Docker Compose

services:
  app:
    image: diolektor/tokio_php:php8.4-alpine3.23
    ports:
      - "8080:8080"
      - "9090:9090"
    environment:
      PHP_WORKERS: 8
      INDEX_FILE: index.php
      DOCUMENT_ROOT: /var/www/html/public
      INTERNAL_ADDR: 0.0.0.0:9090
    volumes:
      - ./:/var/www/html

⁠Supported PHP Features

  • Full superglobals: $_GET, $_POST, $_SERVER, $_COOKIE, $_FILES, $_REQUEST
  • OPcache with JIT (tracing mode)
  • Preloading support via opcache.preload
  • All standard PHP extensions

⁠License

AGPL-3.0

Tag summary

Content type

Image

Digest

sha256:5a5f647d0…

Size

51.5 MB

Last updated

8 months ago

docker pull diolektor/tokio_php