2.1-Instalación de Docker (nuevo método oficial), configuración de un proyecto Laravel con Nginx y MySQL en contenedores
Solución recomendada
En tu terminal WSL, ejecuta:
sudo chown -R $USER:$USER ~/laravel
Te pedirá tu contraseña de Linux.
Después verifica:
ls -l ~/laravel/docker-compose/nginx/app.laravel.conf
Instalación de Docker (nuevo método oficial), configuración de un proyecto Laravel con Nginx y MySQL en contenedores
Este tutorial te guiará paso a paso desde la instalación de Docker y Docker Compose (como plugin) en Linux (Debian/Ubuntu) hasta la configuración completa de un entorno de desarrollo para Laravel con tres servicios: PHP-FPM, Nginx y MySQL. Además, entenderás el funcionamiento de los volúmenes (bind mounts) que sincronizan automáticamente los archivos entre tu máquina host y los contenedores.
Novedad: Hoy en día Docker Compose se instala como un plugin y se utiliza con el comando docker compose (con espacio, sin guion). El antiguo docker-compose (con guion) está en desuso. A lo largo de este tutorial usaremos la sintaxis moderna.
Tabla de contenido
¿Qué son los volúmenes en Docker y por qué son mágicos?
Instalación de Docker y Docker Compose (método oficial)
Estructura de archivos inicial
Creación del Dockerfile personalizado
Creación del archivo docker-compose.yml (servicio app)
Construir y levantar el contenedor de la aplicación
Creación del proyecto Laravel dentro del contenedor
Verificar la sincronización en tiempo real
Configurar Nginx y MySQL
Paso 1: Detener contenedores y crear estructura para Nginx
Paso 2: Crear archivo de configuración de Nginx
Paso 3: Modificar docker-compose.yml (agregar Nginx y MySQL)
Paso 4: Ajustar el archivo .env de Laravel
Paso 5: Levantar los contenedores con la nueva configuración
Paso 6: Verificar que la aplicación funciona
Solución de problemas comunes
Conclusión
Comandos útiles de Docker Compose (nueva sintaxis)
¿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 monta un directorio del host dentro del contenedor.
La sintaxis en
docker-compose.ymles:
volumes:
- ./ruta/local:/ruta/en/contenedorCualquier 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:
volumes:
- ./:/var/wwwEs decir, el directorio actual (donde tienes tu proyecto) se monta en /var/www dentro del contenedor. Todos los archivos de Laravel vivirán ahí.
Instalación de Docker y Docker Compose (método oficial)
Sigue estos pasos para instalar Docker y Docker Compose (como plugin) usando el repositorio oficial. Este es el método recomendado actualmente.
1. Actualizar paquetes e instalar dependencias
sudo apt update
sudo apt install ca-certificates curl -y2. Agregar la clave GPG oficial de Docker
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.asc3. Agregar el repositorio oficial de Docker a las fuentes de APT
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/null4. Actualizar el índice de paquetes e instalar Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -ydocker-ce: El motor de Docker (Community Edition).docker-compose-plugin: El plugin de Docker Compose (ya no necesitas instalardocker-composepor separado).
5. Verificar la instalación
Para confirmar que todo ha ido bien, ejecuta el contenedor de prueba:
sudo docker run hello-worldDeberías ver el mensaje de bienvenida de Docker.
6. Agregar tu usuario al grupo docker (para evitar usar sudo)
sudo groupadd docker # si no existe
sudo usermod -aG docker $USERPara aplicar los cambios sin cerrar sesión:
newgrp dockerPrueba que todo funciona sin sudo:
docker run hello-world7. Verificar la versión de Docker Compose
Con el nuevo plugin, el comando es docker compose (con espacio). Verifica que está instalado:
docker compose versionDeberías ver algo como Docker Compose version v2.xx.x. Si ves esto, estás listo para usar la sintaxis moderna.
Estructura de archivos inicial
Antes de empezar, asegúrate de tener una carpeta vacía para tu proyecto. Nosotros la llamaremos laravel-docker (puedes elegir cualquier nombre).
Crear la carpeta:
mkdir laravel-docker
cd laravel-dockerÁrbol inicial en el host:
~/laravel-docker/
├── Dockerfile (lo crearemos)
└── docker-compose.yml (lo crearemos)Creación del Dockerfile personalizado
Vamos a crear un Dockerfile que defina la imagen de nuestro contenedor principal (PHP-FPM). Este contenedor ejecutará el código de Laravel.
Crear el archivo Dockerfile
Dentro de ~/laravel-docker/, ejecuta:
nano DockerfilePega el siguiente contenido (explicado línea por línea):
# 1. Imagen base: PHP 8.3 con FPM (recomendado para Laravel 10/11)
FROM php:8.3-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:8.2-fpm: imagen base ligera con PHP 8.2 y FPM.ARG USERyARG 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-datayroot.El directorio de trabajo es
/var/www.Cambiamos al usuario creado para que los comandos se ejecuten con sus permisos.
Creación del archivo docker-compose.yml (servicio app)
Este archivo orquesta nuestros servicios. Definiremos el servicio app (nuestro contenedor PHP-FPM). Más adelante añadiremos MySQL y Nginx.
Crear docker-compose.yml
nano docker-compose.ymlPega el siguiente contenido:
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: bridgePuntos clave:
build: construye la imagen a partir del Dockerfile del directorio actual, pasando los argumentosuseryuid. Para obtener el UID actual de tu usuario, ejecutaid -uy asígnalo a una variable de entorno o simplemente usa 1000.volumes: - ./:/var/www: bind mount que monta el directorio local dentro del contenedor en/var/www. Este es el corazón de la sincronización.networks: crea una red internalaravelpara que los servicios se comuniquen entre sí.
Construir y levantar el contenedor de la aplicación
Ejecutar docker compose up -d
Nota: Usamos el nuevo comando docker compose (sin guion).
docker compose up -dSi tienes instalada la versión independiente de Docker Compose (v1), el comando correcto es:
docker-compose up -dEste comando:
Construye la imagen según el Dockerfile (descarga la base
php:8.2-fpmy ejecuta los pasos).Crea el contenedor
laravel-app-1y 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. Como ya se habrán descargado algunas capas, el proceso continuará más rápido.
Verificar que el contenedor está corriendo
docker psDeberías ver algo como:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
xxxxxxxxxxxx laravel-app "docker-php-entrypoi…" ... seconds Up ... laravel-app-1Comandos útiles:
Detener el contenedor:
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>Vercontenedoresdocker psconstruir contenedor:docker compose up -d
Ingresar al contenedor:docker exec -it laravel-app-1 /bin/bash
Salir del contenedor:exit
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.
Acceder al contenedor
docker exec -it laravel-app-1 /bin/bashAhora estás dentro del contenedor como el usuario que definiste. El prompt debería mostrar algo como udemy@<container_id>:/var/www$.
Crear el proyecto Laravel
Dentro del contenedor, ejecuta:
composer create-project laravel/laravel application --prefer-distComposer 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):
~/laravel-docker/
├── application/
│ ├── app/
│ ├── bootstrap/
│ ├── config/
│ ├── database/
│ ├── public/
│ ├── resources/
│ ├── routes/
│ ├── storage/
│ ├── tests/
│ ├── vendor/
│ ├── .env
│ ├── composer.json
│ └── ... (otros archivos)
├── Dockerfile
└── docker-compose.ymlEstructura en el contenedor: exactamente la misma, porque /var/www está montado sobre el directorio del host. Ambos comparten el mismo árbol de archivos.
Copiar los archivos al directorio raíz y eliminar la subcarpeta application
Para que el código quede directamente en /var/www y no en una subcarpeta, podemos mover todos los archivos de application/ a la raíz del proyecto.
Desde el host (fuera del contenedor):
cp -RT application/ .
rm -rf applicationO desde dentro del contenedor:
cp -RT application/ . && rm -rf applicationVerifica que la estructura ahora sea:
~/laravel-docker/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
├── tests/
├── vendor/
├── .env
├── composer.json
├── Dockerfile
└── docker-compose.ymlGenerar la clave de la aplicación (APP_KEY)
Dentro del contenedor (o desde el host, pero es mejor dentro para asegurar permisos), ejecuta:
php artisan key:generateEsto modificará el archivo .env que está sincronizado, así que verás el cambio en el host.
Lo más recomendable es ejecutar php artisan key:generate dentro del contenedor, no en el host.
Verificar la sincronización en tiempo real
Para confirmar que el bind mount funciona, realiza una prueba:
Desde el host, crea un archivo
test.txtdentro de~/laravel-docker/.Dentro del contenedor, ejecuta
ls /var/wwwy verástest.txt.Desde el contenedor, crea otro archivo
touch /var/www/from-container.txt.En el host, verás que aparece
from-container.txtautomáticamente.
Esto demuestra que el directorio es compartido en ambos sentidos.
Configurar Nginx y MySQL.
Comandos útiles:
Detener el contenedor:
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>Vercontenedoresdocker psconstruir contenedor:docker compose up -d
Ingresar al contenedor:docker exec -it laravel-app-1 /bin/bash
Salir del contenedor:exit
Ahora vamos a agregar los servicios de Nginx (servidor web) y MySQL (base de datos) para tener un entorno completo.
Salir del contenedor:exit
Salir del contenedor:exit
Paso 1: Detener contenedores y crear estructura para Nginx
Primero, asegurémonos de que ningún contenedor esté corriendo:
docker compose downdocker stop laravel_app_1
docker compose-down
docker-compose downDetener y eliminar los contenedores
bash
# Detener todos los contenedores
docker stop laravel-app-1 laravel-docker-nginx-1 laravel-docker-db-1
# Eliminar los contenedores
docker rm laravel-app-1 laravel-docker-nginx-1 laravel-docker-db-1
docker rm 533dd6c21efb_laravel_app_1 laravel_nginx_1 laravel_db_1
# Opcional: Eliminar también los volúmenes (base de datos)
docker volume ls
docker volume rm laravel-docker_db_data
Luego, crea la estructura de carpetas para la configuración de Nginx:
mkdir -p docker-compose/nginxPaso 2: Crear archivo de configuración de Nginx
Dentro de docker-compose/nginx, crea un archivo llamado app.laravel.conf:
nano docker-compose/nginx/app.laravel.confcrea:
default.confPega el siguiente contenido (es un boilerplate oficial de Laravel para 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;
}
}Partes clave que debes revisar:
root /var/www/public;→ ruta donde Nginx buscará elindex.php.listen 80;→ puerto en el que escuchará dentro del contenedor.fastcgi_pass app:9000;→ el nombre del contenedor de PHP-FPM (en nuestro casoapp) y el puerto 9000 (el que expone PHP-FPM).
Guarda el archivo (Ctrl+O, Enter) y sal (Ctrl+X).
Paso 3: Modificar docker-compose.yml (agregar Nginx y MySQL)
Ahora editaremos docker-compose.yml para agregar los dos nuevos servicios. Abre el archivo:
nano docker-compose.ymlAgregar el servicio Nginx:
Debajo del servicio app, añade el siguiente bloque (respeta la indentación con dos espacios):
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "8000:80"
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d
networks:
- laravelAgregar el servicio MySQL (db):
Añade otro bloque para la base de datos:
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:
- laravelEl archivo completo debería verse así:
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
user: ${USER:-udemy}
uid: ${UID:-1000}
image: laravel-app
container_name: laravel-app-1
restart: unless-stopped
working_dir: /var/www
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: bridgeGuarda los cambios (Ctrl+O, Enter) y sal (Ctrl+X).
Paso 4: 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:
nano .envBusca o agrega las siguientes líneas (ajusta los valores como desees):
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=secretPuntos importantes:
DB_HOSTdebe serdb(el nombre del servicio en Docker Compose). No useslocalhostni127.0.0.1, porque dentro del contenedor de la aplicación,localhostsería él mismo, no la base de datos.DB_DATABASE,DB_USERNAMEyDB_PASSWORDdeben coincidir con lo que definiste en elenvironmentdel serviciodb.El puerto
3306es el predeterminado de MySQL.
Guarda el archivo.
Paso 5: Levantar los contenedores con la nueva configuración
Ahora que todo está listo, levanta los servicios con Docker Compose (nuevo comando):
docker-compose down -v # elimina contenedores y volúmenes viejosdocker compose up -dEste 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.
Verifica que los tres contenedores estén en ejecución:
docker psDeberías ver app, nginx y db en la lista.
docker exec -it laravel-app-1 php artisan key:generatePaso 6: 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 algún error, revisa los logs con:
docker compose logs nginx
docker compose logs app
docker compose logs dbSolución de problemas comunes
La descarga de imágenes se queda pegada
Si al levantar los contenedores ves que la descarga de una imagen se detiene sin avanzar, presiona Ctrl + C para cancelar y vuelve a ejecutar docker compose up -d. Como muchas capas ya están descargadas, el proceso continuará más rápido.
Error de conexión a la base de datos
Verifica que
DB_HOSTen.envseadby nolocalhost.Comprueba que los nombres de usuario y contraseña coincidan con los definidos en
environmentdel serviciodb.Asegúrate de que el servicio
dbesté corriendo:docker ps | grep db.
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.
Composer no se encuentra dentro del contenedor
Verifica que en tu Dockerfile hayas instalado Composer correctamente (con COPY --from=composer:latest o con el instalador).
El contenedor no se crea correctamente
Revisa los logs con docker compose logs para identificar errores específicos.
Conclusión
Has configurado exitosamente un entorno completo de desarrollo para Laravel con Docker, que incluye:
PHP-FPM con todas las extensiones necesarias.
Composer para la gestión de dependencias.
Nginx como servidor web.
MySQL como base de datos.
Volúmenes (bind mounts) que sincronizan los archivos entre el host y los contenedores.
Ahora puedes desarrollar tu aplicación Laravel editando los archivos en tu máquina local y viendo los cambios reflejados automáticamente en los contenedores, todo con un entorno aislado y reproducible.
Comandos útiles de Docker Compose (nueva sintaxis)
| Comando | Descripción |
|---|---|
docker compose up -d | Levanta los contenedores en segundo plano |
docker compose down | Detiene y elimina los contenedores |
docker compose logs | Muestra los logs de todos los servicios |
docker compose logs nginx | Muestra los logs de un servicio específico |
docker compose exec app bash | Accede a la terminal del contenedor app |
docker compose restart | Reinicia todos los servicios |
docker compose build | Reconstruye las imágenes sin levantar los contenedores |
Nota: El antiguo comando docker-compose (con guion) ya no es necesario; ahora usamos docker compose (con espacio) como plugin integrado.
Reinicia los contenedores para asegurar que la red se establezca correctamente:
docker compose down docker compose up -ddocker-compose up -dVerifica que el
.envtengaDB_HOST=dbexactamente (sin espacios, sin comillas, sinlocalhost).Prueba la conectividad desde dentro del contenedor
app:docker exec -it laravel-app-1 bash ping dbSi el ping falla, entonces el nombre
dbno se está resolviendo. Si el ping funciona, el problema está en la configuración de PHP (quizás el puerto o las credenciales).Si el ping falla, asegúrate de que el servicio
dbesté definido con el nombre correcto endocker-compose.yml. Si lo llamaste de otra forma (ej.mysql), entonces cambiaDB_HOSTpor ese nombre.
Nota adicional: si no quieres usar contraseña en MySQL
En tu docker-compose.yml, en el servicio db, puedes añadir:
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_DATABASE: ${DB_DATABASE}
# No definas MYSQL_USER ni MYSQL_PASSWORDLuego, en .env:
DB_USERNAME=root
DB_PASSWORD=Pero ojo: esto solo es recomendable en desarrollo local.
Opción 1: Usar el usuario root (la más sencilla, sin crear usuario extra)
Modifica tu .env para usar root con contraseña vacía (ya que tienes MYSQL_ALLOW_EMPTY_PASSWORD: yes).
.env (Opción 1)
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=root
DB_PASSWORD=docker-compose.yml (Opción 1)
db:
image: mysql:8
restart: unless-stopped
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes" # Permite que root no tenga contraseña
MYSQL_DATABASE: ${DB_DATABASE}
# No definimos MYSQL_USER ni MYSQL_PASSWORD porque usamos root
networks:
- laravelVentaja: No necesitas crear un usuario adicional, solo usas root.
Desventaja: Es menos seguro (pero para desarrollo local está bien).
Opción 2: Crear un usuario dedicado laravel_user (más recomendable)
Descomenta las variables MYSQL_USER y MYSQL_PASSWORD en el compose, así MySQL creará ese usuario automáticamente. Luego en .env usas ese usuario y su contraseña.
.env (Opción 2)
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=secret # Pon la contraseña que quieras (coincide con MYSQL_PASSWORD)docker-compose.yml (Opción 2)
db:
image: mysql:8
restart: unless-stopped
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes # Permite que root no tenga contraseña (opcional)
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME} # <--- Descomentado
MYSQL_PASSWORD: ${DB_PASSWORD} # <--- Descomentado
# MYSQL_ROOT_PASSWORD no es necesaria si usas ALLOW_EMPTY_PASSWORD
networks:
- laravelVentaja: Mejor práctica, usas un usuario con privilegios limitados a esa base de datos.
Paso obligatorio para ambas opciones
Elimina la línea version: '3' al inicio de tu docker-compose.yml para evitar el warning (ya es obsoleta).
Luego, reinicia los contenedores desde cero para que los cambios en las variables de entorno se apliquen correctamente. Esto borrará los datos antiguos de MySQL (pero no importa, es desarrollo):
docker compose down -v # -v elimina el volumen de MySQL
docker compose up -d
docker-compose up -dVerifica que el contenedor db arranque bien:
docker compose logs dbDeberías ver ready for connections al final.
Finalmente, prueba la conexión desde el contenedor app:
docker exec -it laravel-app-1 php -r "echo gethostbyname('db');"Si devuelve una IP, y los logs de db no muestran errores, entonces visita http://localhost:8000
La tabla sessions no existe
¡Excelente! El error de conexión ya está resuelto (usuario y contraseña funcionan). Ahora el problema es que Laravel está intentando leer la tabla sessions en la base de datos, pero esa tabla aún no existe porque no has ejecutado las migraciones.
Tienes dos opciones para solucionarlo:
Opción A: Ejecutar las migraciones para crear la tabla sessions (y todas las demás)
Esta es la solución más completa y recomendada si planeas usar la base de datos para sesiones, caché, etc.
1. Accede al contenedor app
docker exec -it laravel-app-1 bash2. Ejecuta las migraciones
Dentro del contenedor, ejecuta:
php artisan migrateEsto creará todas las tablas que necesita Laravel, incluyendo sessions, users, password_reset_tokens, failed_jobs, etc.
Cuando te pregunte sobre la base de datos, escribe yes.
Pasos para usar Tinker
1. Acceder a Tinker
Desde tu terminal dentro del contenedor (ya estás en /var/www como udemy), ejecuta:
php artisan tinker
2. Ver el nombre de la base de datos
Dentro de Tinker, escribe:
>>> config('database.connections.mysql.database')
Esto te devolverá el nombre de la base de datos (según tu archivo .env debería ser laravel_db).
3. Listar todas las tablas
Para ver qué tablas existen en la base de datos, puedes usar:
>>> DB::select('SHOW TABLES');
O más elegante con el esquema de Laravel:
>>> use Illuminate\Support\Facades\Schema; >>> Schema::getConnection()->getDoctrineSchemaManager()->listTableNames();
4. Verificar las migraciones ejecutadas
Laravel guarda un registro en la tabla migrations. Puedes consultarla:
>>> DB::table('migrations')->get();
Deberías ver las migraciones que acabas de ejecutar (create_users_table, create_cache_table, create_jobs_table).
5. Consultar datos de una tabla (ej. users)
>>> App\Models\User::all();
O si prefieres usar el DB facade:
>>> DB::table('users')->get();
6. Salir de Tinker
Escribe exit o presiona Ctrl + D.
3. Genera la clave de la aplicación (si no lo hiciste antes)
php artisan key:generate4. Sal del contenedor
exit5. Recarga la página
Ve a http://localhost:8000. Ahora deberías ver la página de bienvenida de Laravel sin errore
Verificación final
Después de ejecutar las migraciones, puedes verificar que la tabla sessions existe:
docker exec -it laravel-app-1 php artisan tinkerDentro de Tinker, escribe:
DB::table('sessions')->get();Si no da error, la tabla existe.
Resumen de comandos para ejecutar ahora
# Entrar al contenedor
docker exec -it laravel-app-1 bash
# Ejecutar migraciones
php artisan migrate
# Generar clave
php artisan key:generate
# Salir
exit
# Recargar http://localhost:8000¡Listo! Ahora tu aplicación Laravel debería funcionar sin errores. 🚀
Comentarios
Publicar un comentario