Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

Local PHP Development: Docker, DDEV and More

For local PHP development there is the built-in web server, official Docker images and tools such as DDEV. What matters is that the same PHP version runs locally as in production.

Last updated 5 min readPHP knowledge

In short: There are three common ways to develop PHP locally: the built-in web server (php -S) for quick experiments, the official PHP Docker images for reproducible environments, and tools such as DDEV that create ready-made project environments for WordPress, TYPO3, Shopware or Laravel. What matters is less the tool than the match: the same PHP version with the same extensions should run locally as in production. For security, though, the runtime on the server is what ultimately counts.

Why a development environment of your own?

Making changes directly on the live server is risky: every typo is immediately visible to customers, and test files tend to be left lying around. A local environment separates experimenting from operations. It is also the place where new PHP versions and security updates are tested first.

For management and IT leadership, the question is therefore not whether a development environment exists but whether it matches the live system. A local environment with PHP 8.4 while production still runs 8.1 conceals problems instead of revealing them. The same applies to the database version, web server and extensions such as intl, gd or pdo_mysql: even a single missing extension can mean an error is only noticed in production.

The options at a glance

Option Suited for Strengths Limits
Built-in server php -S short experiments, small scripts no further software to install no replacement for Nginx or Apache, not for public networks
Official Docker image teams, reproducible environments version can be fixed via tag, close to container operation configuration and interplay of several containers must be built yourself
DDEV CMS and framework projects ready-made project types, database and web server included requires Docker, own conventions
Locally installed PHP individual developers fast, direct versions for several projects are hard to keep in parallel

The built-in web server

Since PHP 5.4, the command line has included a small web server. It starts in the current directory or, with -t, in a different document directory:

php -S localhost:8000 -t public/

Optionally you pass a router script that runs first on every request. The manual is unambiguous in its classification: the server is meant to support development, is not a full-fledged web server and should not be used on a public network. Therefore bind it to localhost, not to 0.0.0.0, otherwise it may be reachable on the company or hotel Wi-Fi. More about the command line under PHP on the command line.

Docker: official PHP images

The official images come in several variants: cli for the command line, apache with Apache and mod_php, fpm for operation behind Nginx or another proxy, plus Alpine variants for small images. A quick start with Apache:

docker run --rm -p 8080:80 -v "$PWD":/var/www/html php:8.4-apache

The images contain the templates php.ini-development and php.ini-production in the directory $PHP_INI_DIR. Locally, the development template makes sense because it displays errors. For production, the image documentation expressly recommends the production template. You install extensions with the bundled helper scripts docker-php-ext-configure, docker-php-ext-install and docker-php-ext-enable. How tags and digests work is explained in Official PHP Docker images.

DDEV: ready-made environments for CMS and frameworks

DDEV builds on Docker and sets up a web server, PHP, a database and auxiliary services for a project. The quick-start guides almost always follow the same pattern:

ddev config --project-type=wordpress --docroot=web
ddev start
ddev composer install
ddev launch

DDEV knows project types including wordpress, typo3, shopware6, laravel, symfony, drupal11, magento2 and the generic type php. You set the PHP version in .ddev/config.yaml; according to the documentation, versions from 5.6 to 8.5 are possible, and the default is 8.4:

# .ddev/config.yaml (excerpt)
php_version: "8.3"
webserver_type: nginx-fpm   # alternatively apache-fpm

That way the local environment matches the live version, even if it is not the latest.

Local development, patch level and PHP2Shell

After PHP2Shell, several platform providers pointed out a typical fallacy. According to its bulletin, Vercel stresses that updating the local development environment, the application code or the plugins is not enough; what is decisive is the PHP runtime that actually serves requests. Having PHP 8.4.27 locally does not protect the server running 8.4.26.

Conversely, the development environment brings risks of its own that can migrate into production:

  1. Development ini in production: display_errors is switched on in php.ini-development. If this file reaches the server, visitors see paths and error messages. See Switching off error output in production.
  2. Forgotten test files: phpinfo() files, database dumps or .env files with credentials do not belong in the deployment.
  3. Open development servers: php -S or containers with published ports on machines in the network.
  4. Outdated images: Local images are not updated by themselves; after a PHP security release, the development environment must also be rebuilt so that tests run with the corrected version.
Tip

Define the PHP version in one place, for example in the Dockerfile or in .ddev/config.yaml, and change it together with the server configuration when updating.

How does PHP SOS help?

In the security maintenance contract, we make sure development and operations fit together:

  • Comparison: We compare PHP version and extensions across development, test and live environments.
  • Update procedure: New PHP releases are applied first in the test environment, then live, each with a restart.
  • Check deployment: We make sure that no development ini, test files or credentials reach the server.
  • Documentation: You know at any time which version is running where.

Frequently asked questions

May I use the built-in PHP web server publicly?

No. The PHP manual states expressly that the server started with php -S is for development and should not be used on a public network. For production, PHP-FPM with Nginx or Apache is the right choice.

What is DDEV?

DDEV is a tool built on Docker that creates ready-made development environments for PHP projects. It knows project types for WordPress, TYPO3, Shopware 6, Laravel, Drupal and other systems.

Is it enough to update the local PHP version?

No. Against flaws like PHP2Shell, what counts is the PHP runtime that actually serves requests, that is, the one on the server. The local environment should have the same version, though, so that tests are meaningful.

Which php.ini do I use locally?

Locally, php.ini-development makes sense because it displays errors. In production, php.ini-production should be used. The official Docker images ship with both templates.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help