Desplegar una aplicación web con Nginx + PHP-FPM en Docker
Dedicados & VPS
1

Escenario real

Vamos a desplegar una aplicación PHP (por ejemplo, un sitio hecho con Laravel, Symfony o código propio) usando dos contenedores separados: uno con Nginx como servidor web y otro con PHP-FPM procesando los scripts. Esta separación es el patrón estándar en producción porque permite escalar Nginx y PHP de forma independiente.

Estructura del proyecto

mi-proyecto/
├── docker-compose.yml
├── .env
├── nginx/
│   └── default.conf
└── src/
    └── public/
        └── index.php

1. Archivo .env

Coloca los valores sensibles y configurables aquí:

APP_PORT=8080
PHP_VERSION=8.2

2. Configuración de Nginx

Guarda esto en nginx/default.conf. Nota cómo fastcgi_pass apunta al hostname app, que será el nombre del servicio PHP:

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

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

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

    location ~ /\.ht {
        deny all;
    }
}

3. docker-compose.yml

services:
  app:
    image: php:${PHP_VERSION}-fpm-alpine
    restart: unless-stopped
    working_dir: /var/www/html
    volumes:
      - ./src:/var/www/html
    networks:
      - web

  nginx:
    image: nginx:1.27-alpine
    restart: unless-stopped
    depends_on:
      - app
    ports:
      - "${APP_PORT}:80"
    volumes:
      - ./src:/var/www/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    networks:
      - web

networks:
  web:

4. Código PHP mínimo

En src/public/index.php pon algo simple para verificar:

<?php
echo "Hola desde PHP " . PHP_VERSION . " corriendo en Docker";
phpinfo();

5. Levantar el stack

docker compose up -d
docker compose ps
docker compose logs -f nginx

Abre tu navegador en http://localhost:8080 y deberías ver la salida de PHP. Si algo falla, revisa los logs del contenedor correspondiente.

Detalles importantes

  • Ambos contenedores montan la misma carpeta ./src en /var/www/html. Nginx necesita los archivos estáticos y PHP-FPM necesita los .php.
  • El mapeo de puerto ${APP_PORT}:80 solo expone Nginx al host. PHP-FPM queda aislado dentro de la red web, como debe ser.
  • Para producción real añade extensiones PHP necesarias (pdo_mysql, opcache, gd) construyendo tu propia imagen con un Dockerfile basado en php:8.2-fpm-alpine.
  • Si usas Laravel, recuerda correr composer install y dar permisos a storage/ y bootstrap/cache/.

Siguientes pasos

Este stack mínimo es la base para agregar una base de datos (MariaDB, PostgreSQL), un Redis para caché, un servicio de certificados TLS con Traefik o Caddy, y pipelines de despliegue automatizado. El patrón Nginx + PHP-FPM con Docker Compose es simple, poderoso y perfectamente válido para sitios en producción de tráfico medio.