Images

php-nginx-dev

The web stack with Xdebug, errors on screen and uncached assets, for local development only.

adamrollogi/php-nginx-dev:{version} is php-nginx plus Xdebug 3.5 and development defaults. Everything on the php-nginx page applies here too.

This image shows PHP errors in responses and disables asset caching. Do not use it in production.

What changes from php-nginx

ChangeDetail
Xdebug installedLoaded when PHP_DEBUGGER=xdebug (the default), configured entirely from environment variables.
PHP_DISPLAY_ERRORS=On, PHP_ERROR_REPORTING=E_ALLErrors are rendered in the response.
Static assets uncachedPaths matching NGINX_NO_CACHE_PATTERN are served with Cache-Control: no-store and sendfile off, so edits on bind mounts show up immediately.

Quick start

docker run --rm -d -p 8080:8080 \
  -e NGINX_PORT=8080 \
  -e XDEBUG_START_WITH_REQUEST=yes \
  -v $(pwd)/public:/var/www/html \
  adamrollogi/php-nginx-dev:8.4

With the default XDEBUG_START_WITH_REQUEST=trigger, a session starts only when the request carries a trigger (the Xdebug browser extension, an XDEBUG_TRIGGER cookie or query parameter). Set it to yes to debug every request.

Variables

VariableDefaultDescription
PHP_DEBUGGERxdebugxdebug or none. With none, Xdebug is not loaded at all.
XDEBUG_MODEdevelop,debugAny Xdebug modes: debug, develop, coverage, profile, trace, gcstats.
XDEBUG_START_WITH_REQUESTtriggeryes, no or trigger.
XDEBUG_CLIENT_HOSThost.docker.internalWhere your IDE listens. Works on Docker Desktop out of the box; on Linux add --add-host=host.docker.internal:host-gateway.
XDEBUG_CLIENT_PORT9003IDE port.
XDEBUG_DISCOVER_CLIENT_HOSTfalseDerive the IDE host from the request instead.
XDEBUG_IDEKEYPHPSTORMIDE key.
XDEBUG_OUTPUT_DIR/tmp/xdebugProfiles and traces land here; mount it to keep them.
XDEBUG_LOG_LEVEL3Xdebug log verbosity.
NGINX_NO_CACHE_PATTERN\.(css|js|map|json|svg|png|jpe?g|gif|webp|avif|ico|woff2?)$Regex of asset paths served uncached. Empty disables the snippet.

Any other Xdebug setting can be passed as php.xdebug.<setting> through the generic override mechanism.

IDE setup

Settings, PHP, Debug: set the Xdebug port to 9003 and enable "Can accept external connections". Add a server under PHP, Servers with host localhost, port 8080, and map your project root to /var/www/html. Click "Start Listening for PHP Debug Connections" and trigger a request.

How it is wired

The dev entrypoint renders /run/php/conf.d/50-xdebug.ini from the variables above and adds that directory to PHP's scan path with PHP_INI_SCAN_DIR=:/run/php/conf.d (the leading colon keeps the stock conf.d). The no-cache snippet is rendered into /run/nginx/after.d/no-cache.conf. It then hands over to the regular php-nginx entrypoint, so logging, drop-ins and every other feature behave identically.

Compose example

compose.yaml
services:
  app:
    image: adamrollogi/php-nginx-dev:8.4
    ports:
      - "8080:8080"
    environment:
      NGINX_PORT: 8080
      XDEBUG_START_WITH_REQUEST: "yes"
      XDEBUG_IDEKEY: VSCODE
    volumes:
      - ./:/var/www/html
      - xdebug:/tmp/xdebug
    extra_hosts:
      - "host.docker.internal:host-gateway"

volumes:
  xdebug: