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};
+}