Creating a simple environment with Docker, PHP 8.4, Composer, Nginx, and MariaDB.

Published: (February 2, 2026 at 07:40 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

First article on this platform – keeping things simple, practical, and easy to follow.

If you’ve ever struggled with installing PHP extensions, configuring Nginx, or setting up a local database, Docker can make your life much easier.
In this guide we’ll build a modern, minimal development stack that runs with a single command.

Stack

  • PHP 8.4 (FPM)
  • Composer
  • Nginx
  • MariaDB
  • Docker & Docker Compose

All services will start together with one command.

Folder Structure

root-folder/
├── docker/
│   ├── nginx/
│   │   └── default.conf
│   └── php/
│       └── Dockerfile
├── src/
│   └── index.php
├── docker-compose.yml
└── composer.json
FolderResponsibility
docker/phpCustom PHP image & extensions
docker/nginxNginx configuration
srcApplication source code

1. PHP Dockerfile

Create docker/php/Dockerfile:

# Base image with PHP 8.4 and FPM
FROM php:8.4-fpm

# Install system dependencies and PHP extensions
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libzip-dev \
    && docker-php-ext-install pdo pdo_mysql zip

# Install Composer from the official image
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

# Set the working directory
WORKDIR /var/www/html

What it does

  • Uses PHP 8.4‑FPM (ideal for Nginx).
  • Installs common tools (git, unzip).
  • Enables essential extensions (pdo, pdo_mysql, zip).
  • Adds Composer without a manual download.

2. Nginx Configuration

Create docker/nginx/default.conf:

server {
    listen 80;
    index index.php index.html;
    root /var/www/html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Key points

  • Listens on port 80.
  • Serves files from /var/www/html.
  • Forwards .php requests to the PHP container via FastCGI.

3. Docker‑Compose File

Create docker-compose.yml in the project root:

version: '3.9'

services:
  php:
    build: ./docker/php
    container_name: php84
    volumes:
      - ./src:/var/www/html
    depends_on:
      - mariadb

  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php

  mariadb:
    image: mariadb:11
    container_name: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app
      MYSQL_USER: app
      MYSQL_PASSWORD: app
    ports:
      - "3306:3306"
    volumes:
      - mariadb_data:/var/lib/mysql

volumes:
  mariadb_data:

Explanation

ServicePurpose
phpBuilds a custom PHP 8.4 image, mounts src/ so changes are reflected instantly, and waits for MariaDB to start.
nginxUses the official Nginx image, maps host port 8080 → container port 80, shares the same code volume, and loads the custom config.
mariadbRuns MariaDB 11, creates a database & user on startup, exposes port 3306 (optional), and stores data in a named volume (mariadb_data).
volumesmariadb_data persists the database across container restarts.

4. Sample PHP Application

Create src/index.php:

 PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );

    echo "PHP is running and connected to MariaDB successfully!";
} catch (PDOException $e) {
    echo "Database connection failed: {$e->getMessage()}";
}
  • Uses PDO (the recommended way to talk to databases in PHP).
  • Connects to MariaDB via the service name mariadb.
  • Prints a success message on a good connection, otherwise shows the error.

5. Composer Configuration

Create composer.json:

{
  "name": "example/docker-php",
  "require": {}
}

Running Composer inside the container

docker compose run --rm php composer install

This uses the same PHP environment defined in Docker, avoiding any local PHP version issues.

6. Bring It All Up

From the project root:

docker compose up -d --build

Open your browser and visit:

http://localhost:8080

You should see:

PHP is running and connected to MariaDB successfully!

If the message appears, PHP, Nginx, and MariaDB are communicating correctly. 🎉

What You Get

  • PHP 8.4 ready for development
  • Composer fully integrated
  • Nginx as a lightweight web server
  • MariaDB with persistent data
  • A clean and isolated development environment

This is a solid starting point for plain PHP projects and APIs.

That’s all for today, folks!

Back to Blog

Related posts

Read more »