From 4f7be18b737da7c7af5230b5caf7d9040789c1cc Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Mon, 24 Aug 2026 16:59:17 +0200 Subject: [PATCH] add docker page, resolve version at build time --- docs/getting-started/docker.md | 13 -- docs/getting-started/docker.mdx | 166 ++++++++++++++++++++++++++ docs/getting-started/installation.mdx | 2 +- docusaurus.config.js | 70 ++++++++++- src/components/ConsoleSample/index.js | 15 +++ 5 files changed, 249 insertions(+), 17 deletions(-) delete mode 100644 docs/getting-started/docker.md create mode 100644 docs/getting-started/docker.mdx create mode 100644 src/components/ConsoleSample/index.js diff --git a/docs/getting-started/docker.md b/docs/getting-started/docker.md deleted file mode 100644 index 0a83c2b..0000000 --- a/docs/getting-started/docker.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Docker ---- - -Run PHP Debugger in a container using an image with the debugger already compiled -into the interpreter, with nothing to install. - -:::note -This page is a work in progress — full documentation is coming soon. -::: - -In the meantime, the [installer](./installation.mdx) covers installing directly -onto your machine. diff --git a/docs/getting-started/docker.mdx b/docs/getting-started/docker.mdx new file mode 100644 index 0000000..21d7090 --- /dev/null +++ b/docs/getting-started/docker.mdx @@ -0,0 +1,166 @@ +--- +title: Docker +--- + +import ConsoleSample from '@site/src/components/ConsoleSample'; + +There are two ways to get PHP Debugger into a container: use a prebuilt image with +the debugger already compiled into the interpreter, or install the extension into +an official PHP image yourself. + +The prebuilt images are the simpler route and the one to reach for unless you have +a reason not to. + +## Prebuilt images + +The images on Docker Hub are drop-in replacements for the +[official PHP images](https://hub.docker.com/_/php). Change one line: + +```dockerfile +# before +FROM php:8.4-fpm + +# after +FROM phpdebugger/php:8.4-fpm +``` + +That is the whole setup. There is no extension to install, nothing to enable, and +no separate Dockerfile for development. + +### Available tags + +Each tag matches the official `php:` tag of the same name, for PHP **8.2** to +**8.5**, on `linux/amd64` and `linux/arm64`: + +| Tag | Distro | +| --- | --- | +| `8.x-cli` (also `8.x`) | Debian | +| `8.x-fpm` | Debian | +| `8.x-apache` | Debian | +| `8.x-zts` | Debian | +| `8.x-cli-alpine` (also `8.x-alpine`) | Alpine | +| `8.x-fpm-alpine` | Alpine | +| `8.x-zts-alpine` | Alpine | +| `latest` | newest stable PHP, cli variant | + +There are no patch-level tags such as `8.4.23`. Each tag always carries the latest +patch release of its PHP minor version, rebuilt weekly and on every debugger +release. + +### What is different from the official image + +Everything you already do keeps working — same entrypoints, same helper scripts, +same config layout: + +```dockerfile +FROM phpdebugger/php:8.4-fpm + +RUN docker-php-ext-install -j$(nproc) pdo_mysql bcmath +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer +``` + +Two things are not the same: + +- The debugger is compiled into the interpreter as a static extension. It does not + appear in the `.ini` files, and it cannot be uninstalled. +- The JIT compiler is switched off in the bundled opcache build, because it is + incompatible with the debugger's engine hooks. + +If you rebuild opcache yourself, JIT comes back unless you say otherwise: + +```dockerfile +RUN docker-php-ext-configure opcache --disable-opcache-jit \ + && docker-php-ext-install -j$(nproc) opcache +``` + +### Connecting your IDE + +No INI configuration is needed. Debugging is on by default, every request starts a +session, and the debugger connects whenever your IDE is listening — at near-zero +cost when it is not. + +```yaml +services: + app: + image: phpdebugger/php:8.4-fpm + environment: + PHP_DEBUGGER_CONFIG: "client_host=host.docker.internal" + PHP_IDE_CONFIG: "serverName=myapp" + extra_hosts: + - "host.docker.internal:host-gateway" # needed on Linux +``` + +### Checking it worked + +{`$ docker run --rm phpdebugger/php:8.4-cli php -v +PHP 8.4.24 (cli) (built: Aug 3 2026 12:08:27) (NTS) +Copyright (c) The PHP Group +Zend Engine v4.4.24, Copyright (c) Zend Technologies + with Zend OPcache v8.4.24, Copyright (c), by Zend Technologies + with PHP Debugger v__VERSION__, Copyright (c) 2002-2026, by Derick Rethans`} + +:::warning[Development images only] + +Debugging is enabled by default in these images. A debugger gives anyone who can +reach it full access to your source, your variables, and your runtime data, so a +reachable production container is a serious risk. Keep production on the official +`php:` images and use these only where you actually want to debug. + +::: + +### Removing an existing debugger + +If the image you are switching already had a debugger installed, take the old one +out. PHP Debugger presents the same interface for compatibility, so leaving the +previous extension in place means two extensions competing for the same engine +hooks. + +From your Dockerfile and INI files, remove: + +- the line that loads the old extension — `zend_extension=xdebug.so`, or a + `docker-php-ext-enable xdebug` step; +- any `xdebug.mode` setting — debugging is on by default here; +- any `xdebug.start_with_request` setting — every request already starts a session. + +Settings worth keeping can stay as they are. Both the `xdebug.*` and +`php_debugger.*` prefixes are accepted, so an existing client host or port carries +over untouched. + +## Installing the extension with PIE + +If you would rather keep the official image and add the debugger to it, install +the extension with [PIE](https://github.com/php/pie), the PHP Foundation's +extension installer. + +```dockerfile +FROM php:8.4-cli + +RUN apt-get update \ + && apt-get install -y --no-install-recommends $PHPIZE_DEPS unzip libtool \ + && curl -fsSL https://github.com/php/pie/releases/latest/download/pie.phar \ + -o /usr/local/bin/pie \ + && chmod +x /usr/local/bin/pie \ + && pie install php-debugger/php-debugger \ + && rm -rf /var/lib/apt/lists/* +``` + +PIE compiles the extension against the PHP in the image and enables it for you. +The defaults match the prebuilt images: debugging on, a session with every +request, port 9003. + +Build the image, then check the debugger is in it: + +{`$ docker build -t myapp . +$ docker run --rm myapp php -v +... + with PHP Debugger v__VERSION__, Copyright (c) 2002-2026, by Derick Rethans`} + +The trade-off against the prebuilt images is build time and image size: you are +compiling a C extension and carrying the build toolchain, rather than pulling an +image that already has the debugger in it. + +## Next steps + +- [More install options](./install-options.md) — prebuilt binaries, package + managers, and building from source +- [Configuration](./configuration.md) — the settings you can change diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index 909f442..1227540 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -18,7 +18,7 @@ else. :::tip[Prefer Docker?] -Use a container image instead — see [Docker](./docker.md). +Use a container image instead — see [Docker](./docker.mdx). ::: diff --git a/docusaurus.config.js b/docusaurus.config.js index bb2491c..4fc1f50 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -5,6 +5,43 @@ import {themes as prismThemes} from 'prism-react-renderer'; +/* The released version is shown in the navbar and quoted in sample output on the + docs. Read it from the extension's latest GitHub release at build time so a + rebuild is all it takes to pick up a new release, rather than hunting down + every place a version is written down. + + FALLBACK_VERSION keeps builds working when the API cannot be reached -- offline, + or rate limited, since this is an unauthenticated request. It is only a + backstop: bump it when it drifts too far from reality. */ +const FALLBACK_VERSION = '0.3.0'; + +/* Stand-in written into the navbar config below and swapped for the real version + in createConfig, so the version lives in exactly one place. */ +const VERSION_PLACEHOLDER = '__VERSION__'; + +async function latestDebuggerVersion() { + const url = + 'https://api.github.com/repos/php-debugger/php-debugger/releases/latest'; + try { + const response = await fetch(url, { + headers: {Accept: 'application/vnd.github+json'}, + }); + if (!response.ok) { + console.warn( + `[version] GitHub returned ${response.status}; falling back to ${FALLBACK_VERSION}`, + ); + return FALLBACK_VERSION; + } + const {tag_name: tag} = await response.json(); + return typeof tag === 'string' ? tag.replace(/^v/, '') : FALLBACK_VERSION; + } catch (error) { + console.warn( + `[version] could not reach GitHub (${error.message}); falling back to ${FALLBACK_VERSION}`, + ); + return FALLBACK_VERSION; + } +} + /** @type {import('@docusaurus/types').Config} */ const config = { title: 'PHP Debugger', @@ -107,11 +144,11 @@ const config = { }, { type: 'dropdown', - label: 'v1.3.0', + label: VERSION_PLACEHOLDER, position: 'right', items: [ { - label: 'v1.3.0 (latest)', + label: `${VERSION_PLACEHOLDER} (latest)`, href: 'https://github.com/php-debugger/php-debugger/releases/latest', }, { @@ -130,4 +167,31 @@ const config = { }), }; -export default config; +export default async function createConfig() { + const debuggerVersion = await latestDebuggerVersion(); + const navbar = config.themeConfig.navbar; + return { + ...config, + /* Available to pages via useDocusaurusContext().siteConfig.customFields. */ + customFields: {...config.customFields, debuggerVersion}, + themeConfig: { + ...config.themeConfig, + navbar: { + ...navbar, + items: navbar.items.map((item) => + item.type === 'dropdown' && item.label === VERSION_PLACEHOLDER + ? { + ...item, + label: `v${debuggerVersion}`, + items: item.items.map((sub) => + sub.label === `${VERSION_PLACEHOLDER} (latest)` + ? {...sub, label: `v${debuggerVersion} (latest)`} + : sub, + ), + } + : item, + ), + }, + }, + }; +} diff --git a/src/components/ConsoleSample/index.js b/src/components/ConsoleSample/index.js new file mode 100644 index 0000000..152f24c --- /dev/null +++ b/src/components/ConsoleSample/index.js @@ -0,0 +1,15 @@ +import CodeBlock from '@theme/CodeBlock'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +/* Console output with __VERSION__ swapped for the release the docs were built + against. Sample output that quotes a version goes stale the moment a new one + ships; this way a rebuild is enough to correct it. The version itself is + resolved in docusaurus.config.js. */ +export default function ConsoleSample({children}) { + const {siteConfig} = useDocusaurusContext(); + const text = String(children).replace( + /__VERSION__/g, + siteConfig.customFields.debuggerVersion, + ); + return {text}; +}