A LAMP Stack in Docker Compose

Containers pin every version in a file you commit, so every developer and the CI server run identical builds. Inside WSL 6 , add Docker 514 's apt repository for Ubuntu 26.04 225 as docs.docker.com shows, then sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin (Docker 29.8.1 and Compose v5.5.1 here). Ubuntu's older docker.io package conflicts with it, and unlike Docker Desktop 514 this needs no Windows app running.

compose.yaml: Apache with PHP 8.5, and MySQL 9.7 LTSYAML
services:
  web:
    build:
      dockerfile_inline: |
        FROM php:8.5-apache
        RUN docker-php-ext-install pdo_mysql
    ports: ["8091:80"]
    volumes: ["./src:/var/www/html"]
    depends_on: {db: {condition: service_healthy}}
  db:
    image: mysql:9.7
    ports: ["127.0.0.1:3391:3306"]
    environment: {MYSQL_ROOT_PASSWORD: rootpw, MYSQL_DATABASE: app, MYSQL_USER: app,
                  MYSQL_PASSWORD: secret}
    volumes: ["dbdata:/var/lib/mysql"]
    healthcheck: {test: "mysqladmin ping -h 127.0.0.1 -prootpw", interval: 5s, retries: 20}
volumes: {dbdata: {}}

The inline Dockerfile adds the pdo_mysql driver the official image lacks. Ports 8091 and 3391 avoid the native Apache 129 and MySQL 524 , 127.0.0.1 keeps MySQL off the network, the web container waits for a healthy database, and the dbdata volume keeps the data. Inside the network, the database host is db:

A page that reports both versions, and the stack brought upShell
mkdir src && cat > src/index.php <<'PHP'
<?php
$pdo = new PDO('mysql:host=db;dbname=app', 'app', 'secret');
echo 'PHP ', PHP_VERSION, ' on ', $_SERVER['SERVER_SOFTWARE'], "\n";
echo 'MySQL ', $pdo->query('SELECT VERSION()')->fetchColumn(), "\n";
PHP
docker compose up -d --build --quiet-build
docker compose ps --format 'table {{.Service}}\t{{.Status}}\t{{.Ports}}'
curl -s http://localhost:8091/
Output
...
 Container lamp-web-1 Started
SERVICE   STATUS                    PORTS
db        Up 21 seconds (healthy)   33060/tcp, 127.0.0.1:3391->3306/tcp
web       Up Less than a second     0.0.0.0:8091->80/tcp, [::]:8091->80/tcp
PHP 8.5.10 on Apache/2.4.68 (Debian)
MySQL 9.7.2

The images are newer than Ubuntu's packages, a difference worth writing down. docker compose down stops the stack, down -v also deletes the database, and real passwords belong in an .env file kept out of git.