PHP cookbook · Beginner
Set up a PHP dev environment with Docker Compose
Give every developer the same PHP, database and Redis versions with one command.
Approach
Define PHP-FPM, Nginx, PostgreSQL/MySQL and Redis in compose.yaml, mount the source code for live editing, keep data in named volumes, and pass configuration via environment variables. Add Xdebug only in the dev image.
Solution
# compose.yaml
services:
php:
build: { context: ., dockerfile: docker/php/Dockerfile, target: dev }
volumes: [".:/var/www/app"]
environment:
DB_DSN: "pgsql:host=db;dbname=app"
DB_USER: app
DB_PASSWORD: secret
REDIS_HOST: redis
depends_on:
db: { condition: service_healthy }
nginx:
image: nginx:1.27-alpine
ports: ["8080:80"]
volumes:
- ".:/var/www/app:ro"
- "./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro"
depends_on: [php]
db:
image: postgres:17-alpine
environment: { POSTGRES_DB: app, POSTGRES_USER: app, POSTGRES_PASSWORD: secret }
volumes: ["dbdata:/var/lib/postgresql/data"]
healthcheck: { test: ["CMD", "pg_isready", "-U", "app"], interval: 5s, retries: 10 }
redis:
image: redis:7-alpine
volumes:
dbdata:
# docker/php/Dockerfile
FROM php:8.4-fpm-alpine AS base
RUN docker-php-ext-install pdo_pgsql opcache
FROM base AS dev
RUN apk add --no-cache $PHPIZE_DEPS linux-headers && pecl install xdebug redis && docker-php-ext-enable xdebug redis
Pitfalls
- Using
latesttags so environments drift. - Committing real credentials in compose files.
- Slow bind mounts on macOS for
vendor/— consider a named volume for it.
Variations
- Laravel Sail or DDEV provide preconfigured setups.
- FrankenPHP image as an all-in-one server.
Further reading: Docker Compose documentation
Reference: https://docs.docker.com/compose/
More PHP recipes
- Add CSRF protection to PHP forms
- Add health check endpoints to a PHP app
- Add structured logging with request IDs in PHP
- Build a secure password reset flow in PHP
- Cache expensive queries with Redis in PHP
- Call external APIs with timeouts and retries in PHP
- Handle file uploads securely in PHP
- Implement rate limiting in a PHP API