5.3Docker for PHP: reproducible environments
The essentials in 30 seconds
- The end of “it works on my machine”: the container ships the app with its environment (PHP version, extensions, config) and runs identically everywhere.
- Image → container: the Dockerfile describes the recipe (PHP image, extensions, Composer), docker build freezes the image, docker run starts the container.
- Compose for the stack: PHP + database + cache described in one file and started together — one-command onboarding.
Running case — Riad containerises in Constantine
Riad's optimised shop runs perfectly on his machine in Constantine — but crashes on his colleague's (different PHP version, missing PDO extension, Windows/Linux case breakage). He writes a Dockerfile: PHP image, extensions installed in the image, Composer dependencies. Then a Compose file with MySQL: a single start brings up the whole stack. Sequel of cases 5.1-5.2 — Riad makes his app reproducible everywhere.
Sequel of cases 5.1-5.2 — Riad moves from “it works on my machine” to “the same everywhere”.
1. Containerising PHP: image and container
Docker solves “it works on my machine” — particularly common in PHP (versions, extensions, configuration, Windows/Linux case sensitivity) — by packaging the application with its whole environment (the right PHP version, extensions, configuration, dependencies) in an isolated, portable container that runs identically everywhere: workstation, colleague, server, cloud. Concepts: the image (frozen model of the app + environment, defined by a Dockerfile — the recipe: base PHP image, extensions, copied code, Composer dependencies installed in the image, start command) and the container (running instance of an image). Build (docker build), run (docker run). Riad no longer debates versions: the environment travels with the code.
Reflex: anything specific to your machine and missing from the image is a future crash elsewhere — the image must contain everything (extensions included).
2. Docker Compose and benefits
A realistic PHP application needs several containers cooperating: PHP (with Nginx/Apache), the database (MySQL/MariaDB), possibly Redis. Docker Compose (docker-compose.yml) defines all these containers and their relations, started together with one command (docker compose up). A single file describes the whole stack, reproducible identically — and onboarding becomes trivial: a new developer runs one command and gets the whole environment, without installing or configuring a local pack manually. Benefits: reproducibility (identical everywhere), isolation (projects with different PHP versions coexist without conflict), portability, easy deployment, fast onboarding. Riad adds MySQL to the Compose: his colleague starts in minutes.
Docker is a standard of modern development and a transversal skill: the basics are enough to start, advanced orchestration will come as needed.
3. The right dosage for a PHP developer
No need to become an infrastructure expert: aim for the useful basics — writing a simple PHP Dockerfile, building and running, orchestrating the stack with Compose, aligning the image with production to develop in the same environment as the live release. To learn PHP, a local pack is enough; once you work in a team, manage several projects (different PHP versions) or prepare a deployment, Docker pays off. To avoid: aiming for advanced orchestration before the basics, or containerising a tiny learning script with no real need. Riad keeps his Dockerfile readable: each understood instruction beats a copied recipe.
The right profile: a developer who knows the basics of operations — autonomous, able not only to code but to deliver.
Did you know?
Same image, same behaviour — everywhere.
🔎 Concrete example — Riad's Dockerfile
The PHP image recipe, readable and generic.
FROM php:8.2-apache
RUN docker-php-ext-install pdo pdo_mysql opcache
COPY . /var/www/html/
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
RUN composer install --no-dev --optimize-autoloader
# docker compose up → PHP + MySQL together
Reading: each instruction has a role — PHP base, extensions, code, dependencies, prod optimisation.
Lesson: extensions install INSIDE the image: no more gaps between machines.
Section vocabulary
- Docker
- Tool that packs the app with its environment in a portable container.
Simple example: Riad's shop runs the same in Constantine and on his colleague's machine.
What it is not: a local pack installed by hand on each machine.
Reflex: does my app still depend on my machine?
- Image
- Frozen model of the app + environment, built from the Dockerfile.
Simple example: Riad builds a versioned image of each release.
What it is not: the running container itself.
Reflex: can I rebuild this image identically?
- Dockerfile
- Image build recipe (PHP base, extensions, code, Composer).
Simple example: The readable recipe of Riad's shop, extensions included.
What it is not: a script installing PHP by hand on a server.
Reflex: is each instruction understood, not copied?
- Container
- Running instance of an image, isolated and portable.
Simple example: Riad runs an identical container in dev and staging.
What it is not: the frozen image itself.
Reflex: do dev and prod run the same image?
- Docker Compose
- File describing several containers started together.
Simple example: Riad's PHP + MySQL started with a single command.
What it is not: advanced Kubernetes-style orchestration.
Reflex: does a new dev start in one command?
In practice — Containerising a PHP application
- Write a Dockerfile: start from a PHP image, install the needed extensions, copy the code, install the Composer dependencies.
- Orchestrate the stack with Docker Compose: a docker-compose.yml defining PHP (with Nginx/Apache), MySQL, and possibly Redis, started together (docker compose up).
- Check that the application runs in the containers and talks to its database (environment reproducibility).
- Appreciate the benefits: isolation (per-project PHP versions with no conflict), reproducibility (the end of “it works on my machine”), onboarding (one docker compose up).
Ready-to-say script — proposing Docker to the team
“Our shop works on my machine but not elsewhere: it's an environment problem, not a code one — PHP version, missing extension. I suggest a simple Dockerfile plus a Compose with MySQL. Everyone will run the same image, and a newcomer will start in one command. Secrets will stay out of the image, passed through the environment.”
Say in a team meeting to get containerization adopted without aiming for DevOps expertise.
Copy-paste template — generic PHP Dockerfile + Compose
FROM php:8.2-apache
RUN docker-php-ext-install pdo pdo_mysql opcache
COPY . /var/www/html/
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
RUN composer install --no-dev --optimize-autoloader
# --- docker-compose.yml (generic stack) ---
# services:
# app:
# build: .
# ports: ["8080:80"]
# environment:
# - DB_HOST=db
# db:
# image: mysql:8.0
# environment:
# - MYSQL_DATABASE=boutique
# - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root
Solo / small budget
Riad alone: a simple Dockerfile with no Compose is enough — the image already freezes the PHP environment.
Small business / small team
PHP + MySQL Compose: each colleague starts the full stack with no manual installation.
SME in Constantine
Riad shares the image with the team in Constantine: everyone tests the same version, the end of machine gaps.
Starting team
Pair: one writes the Dockerfile, the other re-reads it line by line; build tested on two machines before adoption.
✓ Best practices
- Install extensions INSIDE the image (no more gaps between machines).
- Align the image with production (same PHP version, same extensions).
- Use Docker Compose to orchestrate the stack (fast onboarding).
✗ Common pitfalls
- Forgetting a PHP extension in the image (crashes elsewhere, not on your machine).
- Putting secrets in the Dockerfile or the image (readable by all).
- Wanting to master advanced orchestration before the basics.
Key takeaways
- DOCKER (containerization) packs the application WITH its environment (PHP, extensions, config, dependencies) in an isolated, portable CONTAINER that runs IDENTICALLY everywhere — the end of “it works on my machine” (common in PHP).
- IMAGE (frozen model, defined by a DOCKERFILE: PHP image + extensions + code + Composer) → CONTAINER (running instance).
- DOCKER COMPOSE (docker-compose.yml) orchestrates the PHP STACK: several containers (PHP/Nginx + MySQL + Redis) started together (`docker compose up`).
- Benefits: REPRODUCIBILITY, ISOLATION (per-project PHP versions with no conflict), portability, easy deployment, fast onboarding. Modern standard (transversal DevOps).
48h challenge — apply tomorrow
Write your app's Dockerfile (template above) and run it in a container: does it answer the same as on your machine?
- I can explain image vs container in one sentence.
- My Dockerfile builds an image that runs.
- I know why secrets do not belong in it.
Frequently asked questions
What does Docker bring a PHP developer, and is it needed when a local pack already works?
A local pack is perfect to start: simple, running in minutes — do not complicate things at first. But its limits appear in a professional context: the environment may differ from production (versions, extensions, config — the classic “it works locally but not online”), managing several projects with different PHP versions is complicated, and the environment is not easily shareable. Docker brings reproducibility (same environment everywhere, including production), isolation (each project its own container, with no version conflict), portability and one-command onboarding. Almost unavoidable in professional development — to learn when you work in a team or prepare a deployment.
Docker, deployment, CI/CD... must a PHP developer become a DevOps expert?
No, not an expert — but knowing the basics changes everything: autonomy (putting your work into production without depending on others), employability (job ads ask for Docker/deployment/CI-CD), better collaboration (apps easy to deploy), a complete vision of the cycle. Aim for the basics: containerizing and Compose (not advanced orchestration), deploying on simple hosting, a simple CI/CD pipeline, secrets and config in environment variables, notions of logs and HTTPS. The right profile: a developer who knows the basics of operations — able not only to code but to deliver.
Which problem does Docker mainly solve?