Introduction: Why Deploy PHP in Kubernetes?
\n\nMany developers still perceive PHP as a language for "classic" hosting with FTP and phpMyAdmin. However, in modern DevOps culture, PHP applications are increasingly run in containers, with their management falling on the shoulders of Kubernetes (K8s). This provides not only automatic scaling and fault tolerance, but also environment consistency across all stages — from development to production.
In this guide, we will walk through how to prepare a PHP project for deployment in Kubernetes: from creating a Docker image to writing manifests and launching it in a cluster. You will learn how to make the container lightweight, how to properly configure php-fpm, and how to tie it all together with Nginx. Let's go!
Step 1: Preparing the PHP Application and Docker Image
\n\nBefore uploading code to K8s, you need to package it into a Docker image. Let's consider a typical PHP project in pure PHP (without a framework) — a simple script that displays a greeting and phpinfo.
\n\n1.1. Project Structure
\n\nLet's create a minimal structure:
\n\nmy-php-app/\n├── src/\n│ └── index.php\n├── docker/\n│ ├── php.Dockerfile\n│ └── nginx.conf\n└── k8s/\n ├── deployment.yaml\n └── service.yaml\n\n\n1.2. PHP Application Code
\n\nFile src/index.php:
<?php\necho "<h1>Hello, Kubernetes!</h1>";\necho "<p>PHP Version: " . phpversion() . "</p>";\necho "<p>Server: " . gethostname() . "</p>";\n?>\n\n\n1.3. Dockerfile for PHP-FPM
\n\nCreate docker/php.Dockerfile:
FROM php:8.2-fpm-alpine\n\n# Install dependencies (if needed)\nRUN docker-php-ext-install pdo pdo_mysql\n\n# Copy application code\nCOPY ./src /var/www/html\n\n# Set permissions (important for FPM)\nRUN chown -R www-data:www-data /var/www/html\n\nWORKDIR /var/www/html\n\nEXPOSE 9000\nCMD ["php-fpm"]\n\n\nWhy alpine? It gives an image size of ~30 MB instead of 200+ MB on Debian. This is critical for fast loading in the cluster.
1.4. Nginx Configuration
\n\nPHP-FPM cannot serve static files directly — a web server is needed. Create docker/nginx.conf:
server {\n listen 80;\n server_name _;\n root /var/www/html;\n\n index index.php index.html;\n\n location / {\n try_files $uri $uri/ /index.php?$query_string;\n }\n\n location ~ \\.php$ {\n fastcgi_pass 127.0.0.1:9000;\n fastcgi_index index.php;\n fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n include fastcgi_params;\n }\n}\n\n\nIn Kubernetes, we will run Nginx and PHP-FPM in the same Pod (as sidecar containers) or as separate services. For simplicity, we'll use one Pod with two containers.
\n\nStep 2: Building and Publishing Images
\n\nLet's build the PHP-FPM image and the Nginx image with our configuration. In a real project, you could use a single image by combining Nginx and PHP with supervisord, but we'll do it the "right" way — separate them.
Building the PHP image:
\ndocker build -t my-php-app:latest -f docker/php.Dockerfile .\n\n\nBuilding the Nginx image:
\nCreate a separate Dockerfile for Nginx:
\nFROM nginx:alpine\nCOPY docker/nginx.conf /etc/nginx/conf.d/default.conf\nCOPY ./src /var/www/html\n\n\ndocker build -t my-nginx:latest -f docker/nginx.Dockerfile .\n\n\nThen upload the images to a registry (Docker Hub, GitLab Container Registry, etc.):
\ndocker tag my-php-app:latest your-registry/my-php-app:latest\ndocker push your-registry/my-php-app:latest\n\n\nStep 3: Kubernetes Manifests
\n\nNow for the interesting part — let's describe how Kubernetes will run our application.
\n\n