PHP-FPM (FastCGI Process Manager) is an alternative FastCGI daemon for PHP that optimizes performance and scalability and can support strenuous loads by managing a pool of PHP worker processes.

While PHP is tightly coupled with Apache, PHP-FPM has its own process manager and is typically coupled with a web server like NGINX or Nginx Proxy Manager.

Deploy a PHP-FPM server

The following tutorial will guide you through the first steps of deploying the Minimus PHP-FPM container image. In this scenario, we will run the PHP-FPM server with Nginx Proxy Manager for SSL certificates.

To begin, authenticate to the Minimus registry:

docker login reg.mini.dev -u minimus 
Password: {Minimus token}

In your project folder, save the following code to a new Docker Compose file compose.yaml:

compose.yaml
services:
  app:
    build:
      context: .
      dockerfile: php/Dockerfile
    restart: unless-stopped
    working_dir: /app
    volumes:
      - ./src:/var/www/html
      - ./data:/data

  nginx:
    build:
      context: .
      dockerfile: nginx/Dockerfile
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    depends_on:
      - app

In the same directory, save the following code to a new file nginx.conf:

nginx.conf
events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # Add fastcgi settings
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;

    # Path to SSL certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

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

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

        location ~ \.php$ {
            fastcgi_pass app:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;

            # Basic fastcgi parameters
            fastcgi_param  QUERY_STRING       $query_string;
            fastcgi_param  REQUEST_METHOD     $request_method;
            fastcgi_param  CONTENT_TYPE       $content_type;
            fastcgi_param  CONTENT_LENGTH     $content_length;

            fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
            fastcgi_param  REQUEST_URI        $request_uri;
            fastcgi_param  DOCUMENT_URI       $document_uri;
            fastcgi_param  DOCUMENT_ROOT      $document_root;
            fastcgi_param  SERVER_PROTOCOL    $server_protocol;
            fastcgi_param  REQUEST_SCHEME     $scheme;
            fastcgi_param  HTTPS              $https if_not_empty;

            fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
            fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

            fastcgi_param  REMOTE_ADDR        $remote_addr;
            fastcgi_param  REMOTE_PORT        $remote_port;
            fastcgi_param  SERVER_ADDR        $server_addr;
            fastcgi_param  SERVER_PORT        $server_port;
            fastcgi_param  SERVER_NAME        $server_name;
        }
    }
}

Create a php folder and save the following code to a Dockerfile in the /php directory:

Dockerfile
FROM reg.mini.dev/php:fpm

# Install any PHP extensions if needed

# Set working directory
WORKDIR /app

# Copy application files
COPY ./src /var/www/html

In theory, you can update the Dockerfile to install PHP extensions, for example: RUN docker-php-ext-install pdo pdo_mysql .

Create an nginx folder and save the following code to a Dockerfile in the /nginx directory:

Dockerfile
FROM reg.mini.dev/nginx-proxy-manager:latest

# Copy nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf

Create a src folder and save the following code to a new file index.php under the /src directory:

index.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>PHP-FPM Welcome</title>
    <meta http-equiv="refresh" content="5">
    <style>
        body {
            font-family: sans-serif;
            margin: 40px;
            background-color: #f9f9f9;
            color: #333;
        }
        .container {
            max-width: 600px;
            padding: 20px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
        }
        h1 {
            color: #007acc;
        }
        p {
            margin: 16px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <?php
            echo "<h1>Welcome to PHP-FPM - Built by Minimus!</h1>";
            echo "<p>👍 Looking great!</p>";
            echo "<p>Your PHP-FPM server is up and running.</p>";

            $currentTime = date("Y-m-d H:i:s");
            echo "<p><strong>Current time:</strong> $currentTime</p>";
        ?>
    </div>
</body>
</html>

Create a directory /letsencrypt .

You project directory should now look like this:

project-root/
├── compose.yaml
├── nginx.conf
├── letsencrypt/
├── nginx/
│   └── Dockerfile
├── php/
│   └── Dockerfile
└── src/
    └── index.php

Run the app:

docker compose up -d

Open your web browser to view the welcome page at: http://localhost:8080. You should see a Minimus greeting with the current time.

Once ready to clean up, run the following command to remove the containers and their associated volumes:

docker compose down -v