2-2:Tutorial: Configurar Nginx y MySQL para Laravel con Docker

 

Tutorial: Configurar Nginx y MySQL para Laravel con Docker

En este tutorial configuraremos los servicios de Nginx (servidor web) y MySQL (base de datos) para nuestro proyecto Laravel, utilizando Docker Compose. Partiremos del contenedor de PHP-FPM que ya tenemos funcionando. Al final, tendremos tres contenedores comunicados entre sí: la aplicación PHP, el servidor web y la base de datos.


Requisitos previos

  • Tener Docker y Docker Compose instalados.

  • Haber seguido el tutorial anterior (creación del proyecto Laravel dentro del contenedor y copia de archivos al host).

  • Tener el archivo docker-compose.yml y el Dockerfile iniciales (con el servicio app para PHP-FPM).


Paso 1: Detener los contenedores actuales

Antes de modificar la configuración, debemos asegurarnos de que ningún contenedor esté corriendo. Ejecuta:

bash
docker ps

Si ves el contenedor de la aplicación (por ejemplo, larabel_app_1), deténlo con:

bash
docker-compose down

Verifica que ya no haya contenedores activos:

bash
docker ps

Paso 2: Crear la estructura de directorios para Nginx

Vamos a crear una carpeta donde guardaremos la configuración de Nginx. Esto nos permitirá modificarla fácilmente desde el host.

bash
mkdir -p docker-compose/nginx
  • La opción -p crea los directorios padres si no existen.

  • Dentro de docker-compose/nginx colocaremos el archivo de configuración del sitio.


Paso 3: Crear el archivo de configuración de Nginx

Dentro de la carpeta docker-compose/nginx, crea un archivo llamado app.laravel.conf (puedes usar cualquier nombre, pero debe terminar en .conf). Usaremos nano para editarlo:

bash
nano docker-compose/nginx/app.laravel.conf

Pega el siguiente contenido (es un boilerplate oficial de Laravel para Nginx). Es importante que revises tres partes clave:

  • root /var/www/public; → ruta donde Nginx buscará el index.php.

  • listen 80; → puerto en el que escuchará dentro del contenedor.

  • fastcgi_pass app:9000; → el nombre del contenedor de PHP-FPM (en nuestro caso app) y el puerto 9000 (el que expone PHP-FPM).

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

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

    index index.php;

    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;
    }
}

Guarda el archivo (Ctrl+O, Enter) y sal (Ctrl+X).


Paso 4: Modificar el archivo docker-compose.yml

Ahora editaremos docker-compose.yml para agregar dos nuevos servicios: nginx y db (MySQL). Abre el archivo:

bash
nano docker-compose.yml

4.1. Agregar el servicio Nginx

Debajo del servicio app (o donde corresponda), añade el siguiente bloque. Respeta la indentación con dos espacios (es la que usa Docker Compose).

yaml
  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "8000:80"
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d
    networks:
      - laravel

Explicación:

  • image: nginx:alpine → usa la versión ligera de Nginx.

  • restart: unless-stopped → se reinicia a menos que lo detengas manualmente.

  • ports: "8000:80" → el puerto 8000 del host se mapea al 80 del contenedor. Accederás a la app en http://localhost:8000.

  • volumes:

    • Monta todo el directorio actual (./) en /var/www dentro del contenedor (para que Nginx sirva los archivos de Laravel).

    • Monta la carpeta ./docker-compose/nginx en /etc/nginx/conf.d (para que Nginx cargue tu archivo de configuración).

  • networks: laravel → conecta este contenedor a la red laravel (debe existir).

4.2. Agregar el servicio MySQL (db)

Añade otro bloque para la base de datos:

yaml
  db:
    image: mysql:8
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
    networks:
      - laravel

Explicación:

  • image: mysql:8 → imagen oficial de MySQL 8.

  • environment → variables de entorno que configuran la base de datos. Usamos variables del archivo .env (veremos a continuación).

  • No exponemos puertos (por defecto usa el 3306 interno, pero no es necesario mapearlo al host a menos que quieras conectarte desde fuera).

4.3. Definir la red (si no existe)

Al final del archivo, fuera de cualquier servicio, añade la definición de la red:

yaml
networks:
  laravel:
    driver: bridge

El archivo completo debería verse similar a esto (solo los servicios relevantes):

yaml
version: '3'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: larabel_app
    restart: unless-stopped
    volumes:
      - ./:/var/www
    networks:
      - laravel

  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "8000:80"
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d
    networks:
      - laravel

  db:
    image: mysql:8
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
    networks:
      - laravel

networks:
  laravel:
    driver: bridge

Guarda los cambios (Ctrl+O, Enter) y sal (Ctrl+X).


Paso 5: Ajustar el archivo .env de Laravel

El archivo .env (en la raíz de tu proyecto) contiene las variables de conexión a la base de datos. Debemos editarlo para que los valores coincidan con los que usaremos en el contenedor db.

Abre el .env:

bash
nano .env

Busca o agrega las siguientes líneas (ajusta los valores como desees):

env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=secret

Puntos importantes:

  • DB_HOST debe ser db (el nombre del servicio en Docker Compose). No uses localhost ni 127.0.0.1, porque dentro del contenedor de la aplicación, localhost sería él mismo, no la base de datos.

  • DB_DATABASE, DB_USERNAME y DB_PASSWORD deben coincidir con lo que definiste en el environment del servicio db. En el ejemplo, usamos laravel_db, laravel_user y secret.

  • El puerto 3306 es el predeterminado de MySQL.

Guarda el archivo.


Paso 6: Levantar los contenedores con la nueva configuración

Ahora que todo está listo, levanta los servicios con Docker Compose en segundo plano:

bash
docker-compose up -d

Este comando construirá la imagen de la aplicación (si no está construida), descargará las imágenes de Nginx y MySQL (si no las tienes), y creará los tres contenedores.

Posibles errores al escribir las variables en docker-compose.yml:

  • Asegúrate de que los nombres de variables de entorno estén escritos correctamente (por ejemplo, MYSQL_DATABASE, no MYSQL_DB).

  • Si usas ${DB_DATABASE}, el archivo .env debe estar en el mismo directorio donde ejecutas docker-compose (y Docker Compose lo lee automáticamente).

Si todo va bien, ejecuta docker ps para ver los tres contenedores en ejecución: app, nginx y db.


Paso 7: Verificar que la aplicación funciona

Abre tu navegador y visita http://localhost:8000. Deberías ver la página de bienvenida de Laravel. Si ves un error, revisa los logs con:

bash
docker-compose logs nginx
docker-compose logs app
docker-compose logs db

Paso 8: Generar la clave de la aplicación (si no se generó automáticamente)

Dentro del contenedor app, ejecuta:

bash
docker exec -it larabel_app php artisan key:generate

Esto creará la clave en el .env. Luego reinicia Nginx (no es necesario, pero por si acaso):

bash
docker-compose restart nginx

Solución de problemas comunes

Error de conexión a la base de datos

  • Verifica que DB_HOST en .env sea db y no localhost.

  • Comprueba que los nombres de usuario y contraseña coincidan con los definidos en environment del servicio db.

  • Si usas MySQL 8, asegúrate de que la variable MYSQL_ROOT_PASSWORD esté definida (en el ejemplo la igualamos a DB_PASSWORD).

Error de permiso en los volúmenes

Si Nginx no puede leer los archivos, ajusta los permisos en el host o usa user: www-data en el servicio app.

El puerto 8000 ya está ocupado

Cambia el puerto en ports (por ejemplo, "8001:80") y accede por ese nuevo puerto.

La configuración de Nginx no se carga

Asegúrate de que el archivo de configuración termine en .conf y esté en la ruta correcta del volumen (./docker-compose/nginx). Dentro del contenedor, Nginx lee todos los archivos .conf en /etc/nginx/conf.d.


Conclusión

Has configurado exitosamente:

  • Nginx como servidor web, sirviendo los archivos de Laravel desde el host y con una configuración personalizada.

  • MySQL como base de datos, con credenciales definidas en el archivo .env.

  • Los tres contenedores (app, nginx, db) se comunican entre sí a través de una red Docker.

Ahora tu aplicación Laravel está lista para ser desarrollada localmente con un entorno completo. En siguientes pasos podrías agregar otras herramientas como Redis, o subir tu proyecto a un servidor en la nube

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