10-Configuración de Docker Compose para Laravel

 

Configuración de Docker Compose para Laravel

¡Exacto! Pero con un matiz importante sobre cómo se obtienen esas imágenes:

Recurso¿Crea imágenes?¿Cómo lo hace?¿Qué imágenes?
Dockerfile✅ SíConstruye (build) desde cero siguiendo tus instrucciones.Solo la de PHP (laravel-app).
docker-compose.yml✅ Sí (indirectamente)Orquesta el proceso. Para app construye usando tu Dockerfile. Para nginx y db descarga (pull) las imágenes ya hechas de internet (Docker Hub).Las 3: PHP (construida), Nginx y MySQL (descargadas).

Además de "crear imágenes", docker-compose hace 3 cosas clave:

  1. Las une en una red (laravel): Para que puedan "escucharse" entre sí. Por ejemplo, Nginx puede hablar con PHP-FPM, y PHP puede conectarse a la base de datos MySQL usando el nombre del servicio (db) como si fuera una dirección.

  2. Crea los contenedores: Toma esas 3 imágenes y las convierte en 3 procesos en ejecución.

  3. Gestiona el ciclo de vida: Las levanta, las reinicia si fallan, y comparte archivos (volúmenes) entre tu PC y los contenedores.


En resumen:

  • Dockerfile → Construye 1 imagen (PHP).

  • docker-composeConstruye 1 (PHP) + Descarga 2 (Nginx, MySQL) + Las conecta en red + Las ejecuta.

Por eso al final ves 3 imágenes y 3 contenedores funcionando como un solo equipo. 

 Dockerfile (la "receta")

  • Sirve para construir una única imagen.

  • Define qué lleva dentro un solo contenedor: sistema operativo, extensiones de PHP, Composer, usuario, etc.

  • Es como los planos de una casa. Solo construyes un entorno (en tu caso, el contenedor PHP-FPM).


⚙️ docker-compose.yml (el "plano de obra completa")

  • Sirve para orquestar y levantar múltiples contenedores a la vez.

  • Define cómo se relacionan varios servicios: el contenedor PHP (hecho con tu Dockerfile), el servidor web (Nginx), la base de datos (MySQL) y Redis.

  • Configura redes, volúmenes (para compartir archivos), puertos y orden de arranque.


▶️ Diferencia práctica:

  • Dockerfile → haces docker build y obtienes 1 contenedor (PHP).

  • docker-compose.yml → haces docker compose up y obtienes todo el ecosistema (PHP + Nginx + MySQL + Redis) funcionando al mismo tiempo, listo para ejecutar Laravel.

En resumen: el Dockerfile construye la pieza, y el docker-compose las une y las pone a funcionar en equipo.

Introducción

En este tutorial crearemos el archivo docker-compose.yml para orquestar nuestros contenedores. Este archivo define todos los servicios necesarios para ejecutar una aplicación Laravel en un entorno Dockerizado.


Paso 1: Corregir Errores del Dockerfile

Antes de continuar, debemos corregir un error en el Dockerfile. El comando apt-get necesita el signo - correctamente:

dockerfile
# ❌ Incorrecto
RUN apt-get update && apt-get install -y curl

# ✅ Correcto
RUN apt-get update && apt-get install -y curl

Paso 2: Verificar el UID del Usuario

Necesitamos saber el UID (User ID) de nuestro usuario actual para mapearlo correctamente:

bash
id -u

Ejemplo de salida:

text
1000

Paso 3: Crear el Archivo docker-compose.yml

3.1 Crear y editar el archivo

bash
nano docker-compose.yml

3.2 Versión actualizada (2024-2026)

Actualmente, la versión 3 es la estándar, pero Docker Compose V2 acepta tanto version como la sintaxis sin versión:

yaml
# Formato actual con versión (compatible)
version: '3.8'

# Formato moderno sin versión (recomendado)
# services:

Paso 4: Estructura Completa del docker-compose.yml

4.1 Configuración del servicio principal (app)

yaml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        USERNAME: ${USER:-laravel}
        USERID: ${UID:-1000}
    image: laravel-app
    container_name: laravel_app
    restart: unless-stopped
    working_dir: /var/www/html
    volumes:
      - ./:/var/www/html
    networks:
      - laravel
    depends_on:
      - db
      - redis
    environment:
      - APP_ENV=local
      - APP_DEBUG=true

4.2 Configuración de redes

yaml
networks:
  laravel:
    driver: bridge

Paso 5: Configuración Avanzada con Servicios Adicionales

5.1 Servicio de Base de Datos (MySQL/MariaDB)

yaml
  db:
    image: mysql:8.0
    container_name: laravel_db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: rootsecret
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - laravel

5.2 Servicio de Base de Datos (PostgreSQL)

yaml
  db:
    image: postgres:15
    container_name: laravel_db
    restart: unless-stopped
    environment:
      POSTGRES_DB: laravel
      POSTGRES_USER: laravel
      POSTGRES_PASSWORD: secret
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - laravel

5.3 Servicio de Redis (Caché/Colas)

yaml
  redis:
    image: redis:7-alpine
    container_name: laravel_redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    networks:
      - laravel

5.4 Servicio Nginx (Servidor Web)

yaml
  nginx:
    image: nginx:alpine
    container_name: laravel_nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    networks:
      - laravel

5.5 Servicio PHPMyAdmin (Opcional)

yaml
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: laravel_phpmyadmin
    restart: unless-stopped
    environment:
      PMA_HOST: db
      PMA_PORT: 3306
      UPLOAD_LIMIT: 100M
    ports:
      - "8080:80"
    networks:
      - laravel

Paso 6: Archivo de Variables de Entorno (.env)

Crear un archivo .env para manejar variables sensibles:

bash
nano .env

Contenido:

env
# Usuario y UID
USER=laravel
UID=1000

# Base de datos
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret

# Redis
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

Paso 7: Configuración de Nginx (Opcional)

Crear directorio y archivo de configuración:

bash
mkdir -p docker/nginx
nano docker/nginx/default.conf

Contenido:

nginx
server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php index.html;

    charset utf-8;

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

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

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

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Paso 8: Actualizaciones y Buenas Prácticas (2024-2026)

✅ Docker Compose V2

El comando con guión está obsoleto:

bash
# ❌ Antes (obsoleto)
docker-compose up -d

# ✅ Ahora (recomendado)
docker compose up -d

✅ Sintaxis sin "version"

Las nuevas versiones de Docker Compose permiten omitir version:

yaml
# Formato moderno (sin version)
services:
  app:
    # ...

✅ Health Checks

Agregar verificaciones de salud para mejorar la confiabilidad:

yaml
  db:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10
      interval: 10s

✅ Replicas y Escalado

Para desarrollo local con escalado:

yaml
  app:
    deploy:
      replicas: 2

Paso 9: Comandos Útiles

9.1 Levantar los servicios

bash
docker compose up -d

9.2 Verificar logs

bash
docker compose logs app

9.3 Detener servicios

bash
docker compose down

9.4 Reconstruir con caché limpia

bash
docker compose build --no-cache

9.5 Ejecutar comandos dentro del contenedor

bash
docker compose exec app composer install
docker compose exec app php artisan migrate
docker compose exec app php artisan key:generate

Resumen: Estructura de Archivos

text
laravel/
├── Dockerfile
├── docker-compose.yml
├── .env
├── docker/
│   └── nginx/
│       └── default.conf
└── src/
    └── (código fuente de Laravel)

Errores Comunes y Soluciones

ErrorCausaSolución
permission deniedUID mapeado incorrectoVerificar id -u y ajustar variable
port already allocatedPuerto en usoCambiar puerto en ports:
Cannot connect to dbRed no configuradaVerificar networks:
No such serviceVersión antigua de ComposeActualizar Docker

¡Listo! Ahora tienes un archivo docker-compose.yml completo y modernizado para tu proyecto Laravel. En el siguiente paso podrás probar la configuración y comenzar a instalar Laravel dentro del contenedor.


RESUMEN RÁPIDO DE COMANDOS

  1. Obtén el ID del contenedor que quieres eliminar:

    bash
    docker ps -a

    Verás una lista como esta:

    text
    CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS
    abc123def456   laravel-app    "php-fpm"     5 minutes ago   Exited (0)
  2. Elimina usando ese ID:

    bash
    docker rm abc123def456

AcciónComando
Crear imagendocker build -t nombre:tag .
Ver imágenesdocker images
Eliminar imagendocker rmi nombre:tag
Crear contenedordocker run -d --name nombre imagen
Ver contenedores activosdocker ps
Ver todos los contenedoresdocker ps -a
Detener contenedordocker stop nombre
Eliminar contenedordocker rm nombre
Eliminar contenedor (forzado)docker rm -f nombre
Eliminar todo lo no usadodocker system prune -a

Comentarios

Entradas más populares de este blog

12. Hola Mundo en Docker.

11¿Qué es Docker? y ¿Por qué debo saberlo?

14. Publish and Detached modes