php runtime and server environment

Containerized Local PHP Environments

Containers let a project describe its PHP runtime instead of relying on whatever PHP version happens to be installed on a developer's laptop. A local container can provide the PHP version, extensions, web server, database client tools, and configuration expected by the project.

This improves repeatability, but it does not remove the need to understand PHP configuration. Containers can still have the wrong extensions, wrong php.ini, wrong user permissions, slow bind mounts, or a different setup from production.

What a PHP container contains

A basic PHP CLI image might look like:

FROM php:8.3-cli

WORKDIR /app

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

RUN docker-php-ext-install pdo_mysql

A PHP-FPM image might use:

FROM php:8.3-fpm

WORKDIR /var/www/app

RUN docker-php-ext-install pdo_mysql opcache

The base image controls the PHP version and SAPI. Extension installation controls what application libraries can use. A container that lacks intl, zip, gd, redis, or pdo_mysql can fail even when the code is correct.

Local source code

During development, source code is often mounted into the container:

services:
  php:
    build: .
    volumes:
      - .:/var/www/app

This makes edits appear immediately inside the container. The tradeoff is that file ownership and filesystem performance can differ by operating system, especially on macOS and Windows.

User and permission issues

If the container writes files as root, the host may end up with files the developer cannot edit easily. If the container user cannot write cache, log, upload, or session directories, the application may fail at runtime.

Good local environments make the expected user clear and document how to run Composer, tests, and framework commands inside the container.

Useful checks

Run checks inside the container, not only on the host:

php -v
php -m
php --ini
composer install
vendor/bin/phpunit

If the application runs in a container, the container is the environment that matters. Host PHP may be useful for convenience, but it does not prove the project runtime is correct.

What containers do not solve

Containers do not automatically:

  • make local match production
  • install every needed extension
  • configure OPcache correctly
  • fix file permission mistakes
  • make database state reproducible
  • remove the need for environment variables
  • make slow tests fast

They are a packaging and isolation tool. The quality still depends on the Dockerfile, Compose file, environment files, documentation, and team habits.

What you should be able to do

After this lesson, you should be able to explain why a PHP project uses containers locally, read a simple Dockerfile, check PHP version/extensions inside the container, and recognise common local container problems around volumes, permissions, and parity.

Practice

Task: Review A Local PHP Container

Write a short checklist for reviewing a local PHP container setup.

Requirements

  • Include PHP version and SAPI checks.
  • Include required extension checks.
  • Include Composer and test commands that should run inside the container.
  • Include a volume or file ownership concern.
  • Include a short note explaining why host PHP is not enough proof.

Check your work

The checklist should help a new developer decide whether their local container is ready to work on the project.

Show solution
Runtime checks
- Run php -v inside the container and confirm the expected PHP version.
- Run php --ini and confirm the loaded configuration path.
- Confirm whether the project expects cli, fpm, or both.

Extension checks
- Run php -m inside the container.
- Confirm required extensions such as pdo_mysql, mbstring, intl, zip, opcache, gd, or redis.

Project commands
- Run composer install inside the container.
- Run the project's test command inside the container.
- Run framework commands inside the container, not against host PHP.

Volumes and permissions
- Confirm source changes on the host appear inside the container.
- Confirm cache, logs, uploads, and generated files are writable by the intended container user.
- Avoid leaving root-owned generated files on the host.

Host PHP is not enough proof because the project runs inside the container. The host may have a different PHP version, different php.ini, different extensions, and different paths from the runtime the application actually uses.