2-Instalación de Docker, Docker Compose y Configuración de un Proyecto Laravel

  • La sintaxis en docker-compose.yml es:
    volumes: - ./ruta/local:/ruta/en/contenedor

El . significa "busca el Dockerfile en la carpeta actual".

¿Qué hace - ./:/var/www/html?

  • ./ es la carpeta actual de tu host (donde está el docker-compose.yml).

  • /var/www/html es la ruta dentro del contenedor.

  • Efecto: Todo lo que esté en ./ se ve dentro del contenedor en /var/www/html, y todo lo que se cree dentro del contenedor en /var/www/html aparecerá automáticamente en tu ./. Es una sincronización bidireccional y en tiempo real.


 El "bind mount" (volumes: - ./:/var/www/html) es el corazón de la sincronización entre tu PC y el contenedor.

***********************

Instalar docker y grupo de usuraio

Instalar Docker desde el repositorio oficial

Sigue estos pasos para configurar el repositorio oficial e instalar Docker.

  1. Actualiza los paquetes e instala las dependencias necesarias:

    bash
    sudo apt update
    sudo apt install ca-certificates curl -y
  2. Agrega la clave GPG oficial de Docker:

    bash
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc
  3. Agrega el repositorio oficial de Docker a las fuentes de APT:

    bash
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
      $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  4. Actualiza el índice de paquetes e instala Docker:

    bash
    sudo apt update
    sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
    • docker-ce: El motor de Docker (Community Edition).

    • docker-compose-plugin: El plugin de Docker Compose, que es la forma moderna de usarlo (ya no necesitas instalar docker-compose por separado).

*******************

Instalación de Docker, Docker Compose y Configuración de un Proyecto Laravel con Volúmenes (Bind Mounts)

Este tutorial te guiará paso a paso en la instalación de Docker y Docker Compose en un sistema Linux (Debian/Ubuntu), y te mostrará cómo configurar un entorno de desarrollo para Laravel utilizando contenedores. En cada etapa, prestaremos especial atención a la estructura de archivos tanto en tu máquina host como dentro de los contenedores, y explicaremos el milagro de los volúmenes (bind mounts) que sincroniza automáticamente ambos mundos.


¿Qué son los volúmenes en Docker y por qué son mágicos?

Cuando trabajamos con contenedores, todo lo que sucede dentro de ellos está aislado del sistema anfitrión. Sin embargo, para desarrollar aplicaciones necesitamos que los cambios en el código se reflejen instantáneamente y que los archivos generados (como los de Composer) estén disponibles en nuestro editor local. Aquí es donde entran los bind mounts:

  • Un bind mount es un tipo de volumen que monta un directorio del host dentro del contenedor.

  • La sintaxis en docker-compose.yml es:
    volumes: - ./ruta/local:/ruta/en/contenedor

  • Cualquier archivo creado, modificado o eliminado en el contenedor dentro de esa ruta, aparece automáticamente en tu host y viceversa.

  • Esto permite editar el código con tu IDE favorito mientras el contenedor ejecuta la aplicación, sin necesidad de reconstruir la imagen.

En este tutorial usaremos el siguiente montaje:

yaml
volumes:
  - ./:/var/www

Es decir, el directorio actual (donde tienes tu proyecto) se monta en /var/www dentro del contenedor. Todos los archivos de Laravel vivirán ahí.


Estructura de archivos inicial (host)

Antes de empezar, asegúrate de tener una carpeta vacía para tu proyecto. Nosotros la llamaremos laravel-docker (puedes elegir cualquier nombre). Dentro de ella crearemos los archivos necesarios.

Crear una carpeta simple: mkdir laravel-docker

Árbol inicial en el host:

text
~/laravel-docker/
├── Dockerfile          (lo crearemos)
└── docker-compose.yml  (lo crearemos)

Paso 1: Instalación de Docker y Docker Compose

1.1 Actualizar paquetes del sistema

bash
sudo apt update
sudo apt upgrade -y

1.2 Instalar Docker

bash
sudo apt-get install docker.io -y

Esto instalará la versión de Docker disponible en los repositorios oficiales de Ubuntu/Debian. Verifica la instalación:

bash
docker version

Deberías ver algo como:

text
Client: Docker Engine - Community
 Version:           19.03.8
 ...

1.3 Iniciar el servicio Docker

bash
sudo systemctl start docker
sudo systemctl enable docker   # para que inicie automáticamente al arrancar

1.4 Instalar Docker Compose

bash
sudo apt-get install docker-compose -y

Verifica:

bash
docker-compose --version

1.5 Agregar tu usuario al grupo docker (para evitar sudo)

bash
sudo groupadd docker          # si no existe
sudo usermod -aG docker $USER

Para aplicar los cambios sin cerrar sesión:

bash
newgrp docker

Prueba que todo funciona sin sudo:

bash
docker run hello-world

Deberías ver el mensaje de bienvenida de Docker.

Estructura de archivos: (aún no ha cambiado, solo tenemos los dos archivos en el host)


Paso 2: Creación del Dockerfile personalizado para Laravel

Vamos a crear un Dockerfile que defina la imagen de nuestro contenedor principal (la aplicación PHP-FPM). Este contenedor ejecutará el código de Laravel.

2.1 Crear el archivo Dockerfile

Dentro de ~/laravel-docker/, ejecuta:

bash
nano Dockerfile

Pega el siguiente contenido (explicado línea por línea más abajo):

dockerfile
# 1. Imagen base: PHP 8.2 con FPM (recomendado para Laravel 10/11)
FROM php:8.2-fpm

# 2. Argumentos para el usuario (se pasan al construir la imagen)
ARG USER=laravel
ARG UID=1000

# 3. Instalar dependencias del sistema y extensiones de PHP
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 4. Instalar extensiones de PHP necesarias para Laravel
RUN docker-php-ext-install \
    pdo_mysql \
    mbstring \
    exif \
    pcntl \
    bcmath \
    gd

# 5. Instalar Composer (globalmente)
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 6. Crear un usuario no root (para seguridad)
RUN useradd -G www-data,root -u ${UID} -d /home/${USER} ${USER} \
    && mkdir -p /home/${USER}/.composer \
    && chown -R ${USER}:${USER} /home/${USER}

# 7. Establecer el directorio de trabajo
WORKDIR /var/www

# 8. Cambiar al usuario creado (a partir de aquí se ejecuta con ese usuario)
USER ${USER}

# 9. Comando por defecto (opcional, se puede sobrescribir en docker-compose)
CMD ["php-fpm"]

Explicación del Dockerfile:

  • FROM php:7.4-fpm: imagen base ligera con PHP 7.4 y FPM.

  • ARG user y ARG uid: permiten pasar el nombre y UID del usuario del host desde docker-compose, para que los archivos creados tengan los mismos propietarios.

  • Instalamos paquetes esenciales y extensiones de PHP (pdo_mysql, mbstring, gd, etc.) necesarias para Laravel.

  • Instalamos Composer globalmente.

  • Creamos un usuario no root con el UID proporcionado, lo agregamos a los grupos www-data y root.

  • El directorio de trabajo es /var/www.

  • Cambiamos al usuario creado para que los comandos se ejecuten con sus permisos.

Estructura de archivos (host): (sigue igual, solo hemos creado Dockerfile)

text
~/laravel-docker/
├── Dockerfile
└── docker-compose.yml   (todavía no creado)

Paso 3: Creación del archivo docker-compose.yml

Este archivo orquesta nuestros servicios. Definiremos el servicio app (nuestro contenedor PHP-FPM), y más adelante añadiremos MySQL y Nginx, pero por ahora nos centramos en la aplicación.

3.1 Crear docker-compose.yml

bash
nano docker-compose.yml

Pega el siguiente contenido:

yaml
version: '3'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        user: ${USER:-udemy}   # Usa el usuario del sistema o 'udemy' por defecto
        uid: ${UID:-1000}      # Usa el UID del sistema o 1000 por defecto
    image: laravel-app
    container_name: laravel-app-1
    restart: unless-stopped
    working_dir: /var/www
    volumes:
      - ./:/var/www            # <-- El bind mount mágico
    networks:
      - laravel

networks:
  laravel:
    driver: bridge

Puntos clave:

  • build: construye la imagen a partir del Dockerfile del directorio actual, pasando los argumentos user y uid. Para obtener el UID actual de tu usuario, puedes ejecutar id -u y asignarlo a una variable de entorno o simplemente usar 1000 si es el típico.

  • volumes: - ./:/var/www: bind mount que monta el directorio local (donde está el proyecto) dentro del contenedor en /var/www. Este es el corazón de la sincronización.

  • networks: crea una red interna laravel para que los servicios se comuniquen entre sí (más adelante añadiremos MySQL y Nginx).

Estructura de archivos (host):

text
~/laravel-docker/
├── Dockerfile
└── docker-compose.yml

Estructura de archivos (contenedor - aún no existe):

Cuando el contenedor se levante, tendrá el directorio /var/www montado, pero inicialmente estará vacío (porque nuestro host también lo está). En el contenedor, el directorio de trabajo es /var/www y el usuario es el que definimos.


Paso 4: Construir y levantar el contenedor

4.1 Ejecutar docker-compose up -d

bash
docker-compose up -d

docker compose up -d

Este comando:

  • Construye la imagen según el Dockerfile (descarga la base php:7.4-fpm y ejecuta los pasos).

  • Crea el contenedor laravel-app-1 y lo inicia en segundo plano (-d).

  • Monta el volumen ./ en /var/www.

Posible problema: La descarga de la imagen base a veces se queda "congelada". Si eso ocurre, presiona Ctrl+C y vuelve a ejecutar el comando.

4.2 Verificar que el contenedor está corriendo

bash
docker ps

Deberías ver algo como:

text
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS   NAMES
xxxxxxxxxxxx   laravel-app   "docker-php-entrypoi…"   ... seconds     Up ...                 laravel-app-1

  • Detener el contenedor si está activo: docker stop <nombre_o_id>.
  • Borrar el contenedor: docker rm <nombre_o_id>.
  • Forzar el borrado de uno activo: docker rm -f <nombre_o_id>.
  • 4.3 Estructura de archivos después del up

    • En el host: la carpeta ~/laravel-docker/ sigue teniendo solo los dos archivos (Dockerfile y docker-compose.yml).

    • En el contenedor: el directorio /var/www está montado y, como está sincronizado con el host, también está vacío. Sin embargo, el contenedor tiene otros directorios del sistema fuera de /var/www.


    Paso 5: Creación del proyecto Laravel dentro del contenedor

    Ahora usaremos Composer (instalado en el contenedor) para crear un nuevo proyecto Laravel dentro de /var/www. Gracias al bind mount, los archivos que genere Composer aparecerán instantáneamente en tu host.

    5.1 Acceder al contenedor

    bash
    docker exec -it laravel-app-1 /bin/bash

    Ahora estás dentro del contenedor como el usuario que definiste (p.ej., udemy). El prompt debería mostrar algo como udemy@<container_id>:/var/www$.

    5.2 Crear el proyecto Laravel

    Dentro del contenedor, ejecuta:

    bash
    composer create-project laravel/laravel application --prefer-dist

    Composer descargará Laravel y creará una carpeta application dentro de /var/www con todos los archivos del framework.

    ¡Milagro de los volúmenes! En el mismo instante, abre tu explorador de archivos en el host (~/laravel-docker/) y verás que aparece una carpeta application con toda la estructura de Laravel. Los archivos se han sincronizado automáticamente desde el contenedor al host.

    Estructura en el host (después de composer create-project):

    text
    ~/laravel-docker/
    ├── application/
    │   ├── app/
    │   ├── bootstrap/
    │   ├── config/
    │   ├── database/
    │   ├── public/
    │   ├── resources/
    │   ├── routes/
    │   ├── storage/
    │   ├── tests/
    │   ├── vendor/
    │   ├── .env
    │   ├── composer.json
    │   └── ... (otros archivos)
    ├── Dockerfile
    └── docker-compose.yml

    Estructura en el contenedor: exactamente la misma, porque /var/www está montado sobre el directorio del host. Ambos comparten el mismo árbol de archivos.

    Revisar el archivo de entorno (.env)

    Una vez creado el proyecto, podemos verificar que se generó el archivo .env (variables de entorno). Dentro del contenedor, navega a la carpeta:

    bash
    cd application

    Luego muestra el contenido del archivo .env con:

    bash
    cat .env

    Si ves las variables de configuración (como APP_NAME, DB_CONNECTION, etc.), significa que la instalación fue exitosa. En el tutorial de referencia, también mencionan que se genera la "key" de la aplicación (aunque en versiones modernas de Laravel se genera automáticamente, si no aparece puedes ejecutar php artisan key:generate más adelante).


    Paso 5: Salir del contenedor

    Cuando hayas terminado de revisar, sal del contenedor con:

    bash
    exit

    Volverás a tu terminal local.

    5.3 Copiar los archivos al directorio raíz y eliminar la subcarpeta application

    Dentro del contenedor (o desde el host, pero es más cómodo hacerlo desde el host), podemos mover todos los archivos de application/ a la raíz del proyecto para que el código quede directamente en /var/www y no en una subcarpeta.

    Desde el host (fuera del contenedor):

    bash
    cp -RT application/ .
    rm -rf application

    O también puedes hacerlo dentro del contenedor:

    bash
    cp -RT application/ . && rm -rf application

    Verifica que la estructura ahora sea:

    text
    ~/laravel-docker/
    ├── app/
    ├── bootstrap/
    ├── config/
    ├── database/
    ├── public/
    ├── resources/
    ├── routes/
    ├── storage/
    ├── tests/
    ├── vendor/
    ├── .env
    ├── composer.json
    ├── Dockerfile
    └── docker-compose.yml

    Y dentro del contenedor /var/www tendrá exactamente lo mismo.

    5.4 Generar la clave de la aplicación (APP_KEY)

    Dentro del contenedor (o desde el host, pero es mejor dentro para asegurar permisos), ejecuta:

    bash
    php artisan key:generate

    Esto modificará el archivo .env que está sincronizado, así que verás el cambio en el host.


    6: Copiar los archivos del proyecto al directorio local

    Dentro del contenedor, el proyecto se creó en la carpeta application. Pero queremos tener esos archivos en nuestra máquina local para poder editarlos con nuestro editor favorito.

    Para copiar todo el contenido de esa carpeta al directorio actual (donde estamos ejecutando los comandos), usamos el comando docker cp (aunque en el archivo original se menciona cp -RT, realmente se puede hacer con docker cp). La forma correcta es:

    bash
    docker cp larabel_app_1:/var/www/html/application/. .

    Nota: Asegúrate de que la ruta dentro del contenedor sea correcta. En el ejemplo, el directorio de trabajo dentro del contenedor es /var/www/html (por eso la carpeta application está ahí). Si tu configuración usa otra ruta, ajústala.

    También podrías haber usado cp -RT application . si ya habías montado un volumen, pero en este caso lo haremos con docker cp para mayor claridad.


    Paso 7: Verificar la copia y eliminar la carpeta temporal

    Ahora, lista los archivos en tu directorio local:

    bash
    ls

    Deberías ver todos los archivos y carpetas de Laravel: app, bootstrap, config, database, public, resources, routes, storage, tests, vendor, .env, etc.

    Como ya copiamos todo, podemos eliminar la carpeta application que se creó dentro del contenedor (esto no es obligatorio, pero libera espacio). Para eliminarla desde el contenedor, puedes volver a entrar y ejecutar:

    bash
    docker exec -it larabel_app_1 rm -rf /var/www/html/application

    O bien, si prefieres mantenerla, no la elimines.


    Paso 6: Verificar la sincronización en tiempo real

    Para confirmar que el bind mount funciona, realiza una prueba:

    1. Desde el host, crea un archivo test.txt dentro de ~/laravel-docker/.

    2. Dentro del contenedor, ejecuta ls /var/www y verás test.txt.

    3. Desde el contenedor, crea otro archivo touch /var/www/from-container.txt.

    4. En el host, verás que aparece from-container.txt automáticamente.

    Esto demuestra que el directorio es compartido en ambos sentidos.


    Paso 7: Configurar Nginx y MySQL (opcional, pero sugerido)

    Aunque el tutorial original se detiene aquí, es común añadir servicios adicionales. Podemos extender el docker-compose.yml para incluir un servidor web (Nginx) y una base de datos (MySQL). Esto no afecta al volumen principal, pero es útil para tener un entorno completo.

    Ejemplo de extensión (no incluido en el tutorial original, pero lo añado como valor añadido):

    yaml
    version: '3'
    
    services:
      app:
        # ... (configuración anterior)
    
      nginx:
        image: nginx:alpine
        container_name: laravel-nginx
        restart: unless-stopped
        ports:
          - "8000:80"
        volumes:
          - ./:/var/www
          - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
          - app
        networks:
          - laravel
    
      db:
        image: mysql:5.7
        container_name: laravel-db
        restart: unless-stopped
        environment:
          MYSQL_DATABASE: laravel
          MYSQL_ROOT_PASSWORD: secret
        volumes:
          - db_data:/var/lib/mysql
        networks:
          - laravel
    
    networks:
      laravel:
        driver: bridge
    
    volumes:
      db_data:

    Esto añadiría Nginx sirviendo en el puerto 8000 y MySQL con un volumen persistente.


    Resumen del flujo de archivos y el bind mount

    MomentoHostContenedorSincronización
    Inicial~/laravel-docker/ (vacío, solo Dockerfile y docker-compose)/var/www (vacío)Montado
    composer create-projectAparece application/ con todos los archivosComposer crea archivos en /var/www/applicationInmediata
    Movemos archivos a la raízTodo el código queda en ~/laravel-docker//var/www contiene el códigoInmediata
    Editamos un archivo en el host (ej. routes/web.php)Cambio visible en el editorEl cambio se refleja instantáneamente dentro del contenedorInmediata
    Ejecutamos php artisan dentro del contenedorLos archivos generados (caches, logs) aparecen en el hostEl comando escribe en /var/wwwInmediata

    Conclusión

    Has instalado Docker y Docker Compose, has creado un entorno personalizado para Laravel y has experimentado el poder de los bind mounts. Ahora puedes desarrollar con total comodidad, editando el código en tu máquina anfitriona mientras el contenedor ejecuta tu aplicación en tiempo real.

    Recuerda: el bind mount ./:/var/www es la clave para que el "milagro" funcione. A partir de aquí, puedes añadir más servicios (Nginx, MySQL, Redis) y seguir construyendo tu entorno de desarrollo.


    *******************************


     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