docker-laravel-enfoque AA bueno
La sintaxis en
docker-compose.ymles:volumes: - ./ruta/local:/ruta/en/contenedor
. significa "busca el Dockerfile en la carpeta actual".¿Qué hace - ./:/var/www/html?
./es la carpeta actual de tu host (donde está eldocker-compose.yml)./var/www/htmles 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/htmlaparecerá 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.
Usar Docker con Laravel
En este tutorial aprenderás a configurar un entorno de desarrollo para Laravel usando Docker y Docker Compose. Con Docker podrás ejecutar tu aplicación en contenedores aislados, lo que facilita la reproducibilidad, evita conflictos de versiones y simplifica el trabajo en equipo.
1. ¿Por qué usar Docker con Laravel?
Entorno consistente: Todos los desarrolladores usan la misma configuración de PHP, base de datos, servidor web, etc.
Aislamiento: Cada servicio (PHP, Nginx, MySQL, Redis) corre en su propio contenedor.
Portabilidad: Puedes mover tu aplicación a cualquier servidor que tenga Docker instalado.
Fácil escalado: Con Docker Compose puedes levantar servicios adicionales fácilmente.
2. Requisitos previos
Antes de empezar, asegúrate de tener instalado:
Docker (descargar)
Docker Compose (viene incluido con Docker Desktop, o se instala por separado en Linux)
Verifica que todo funciona:
docker --version
docker-compose --version3. Crear un proyecto Laravel (opcional)
Si ya tienes un proyecto Laravel, puedes saltar este paso. Si no, crea uno nuevo:
composer create-project laravel/laravel mi-proyecto
cd mi-proyectoNota: Necesitas tener Composer instalado globalmente. Si no, puedes usar la imagen de Composer con Docker, pero para simplificar asumimos que lo tienes.
4. Estructura de archivos que vamos a crear
Dentro de la raíz de tu proyecto Laravel, crea la siguiente estructura:
mi-proyecto/
├── docker/
│ ├── nginx/
│ │ └── default.conf
│ └── php/
│ └── Dockerfile
├── docker-compose.yml
└── .env (el de Laravel)5. Configurar el servicio PHP (Dockerfile)
Creamos un Dockerfile para el servicio PHP-FPM. Este archivo define la imagen que usaremos para ejecutar PHP y Laravel.
Ruta: docker/php/Dockerfile
FROM php:8.2-fpm
# Instalar dependencias del sistema
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Limpiar caché de apt
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Instalar extensiones de PHP necesarias para Laravel
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Instalar Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Establecer directorio de trabajo
WORKDIR /var/www/html
# Copiar los archivos de la aplicación (esto se hará con volúmenes en desarrollo)
# pero copiamos el código fuente para producción (opcional)
# COPY . /var/www/html
# Ajustar permisos (en desarrollo, usaremos el usuario de la máquina anfitriona)
RUN chown -R www-data:www-data /var/www/html
# Exponer el puerto 9000 para PHP-FPM
EXPOSE 9000
CMD ["php-fpm"]6. Configurar Nginx
Creamos un archivo de configuración para Nginx que apunte a Laravel.
Ruta: docker/nginx/default.conf
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; # nombre del servicio en docker-compose
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}7. Docker Compose
El archivo docker-compose.yml define todos los servicios que necesitamos: la aplicación (PHP-FPM), el servidor web (Nginx), la base de datos (MySQL) y opcionalmente Redis.
Ruta: docker-compose.yml (en la raíz del proyecto)
version: '3.8'
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: laravel_app
restart: unless-stopped
working_dir: /var/www/html
volumes:
- ./:/var/www/html
networks:
- laravel
depends_on:
- db
- redis
environment:
- PHP_IDE_CONFIG=serverName=docker
extra_hosts:
- "host.docker.internal:host-gateway" # para acceso a la máquina host
webserver:
image: nginx:alpine
container_name: laravel_webserver
restart: unless-stopped
ports:
- "8000:80"
volumes:
- ./:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- laravel
db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: laraveluser
MYSQL_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql
networks:
- laravel
redis:
image: redis:alpine
container_name: laravel_redis
restart: unless-stopped
ports:
- "6379:6379"
networks:
- laravel
networks:
laravel:
driver: bridge
volumes:
db_data:8. Variables de entorno de Laravel
Ajusta tu archivo .env de Laravel para que se conecte a los servicios definidos en Docker. Edita las variables de conexión a la base de datos:
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=secret
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379Nota:
DB_HOST=dbporque el servicio se llamadben el docker-compose.
9. Construir y ejecutar los contenedores
Desde la raíz del proyecto, ejecuta:
docker-compose up -d --buildEsto construirá las imágenes y levantará los contenedores en segundo plano (-d).
Para ver los logs:
docker-compose logs -fSi todo funciona, deberías poder acceder a tu aplicación en:
http://localhost:8000Deberías ver la página de bienvenida de Laravel.
10. Comandos útiles dentro del contenedor
Para ejecutar comandos de Artisan o Composer dentro del contenedor app, usa:
# Ejecutar comandos de Artisan
docker-compose exec app php artisan migrate
# Ejecutar Composer
docker-compose exec app composer install
# Abrir una shell dentro del contenedor
docker-compose exec app bashSi prefieres ejecutar comandos sin tener que escribir docker-compose exec app cada vez, puedes crear un alias:
alias sail='docker-compose exec app'Luego podrías usar sail php artisan ..., pero el alias no es persistente. En proyectos Laravel, existe Laravel Sail, que es una herramienta oficial que usa Docker y proporciona un script ./vendor/bin/sail. Si usas Sail, la configuración es similar, pero este tutorial es genérico.
11. Migrar y poblar la base de datos
Con los contenedores corriendo, ejecuta:
docker-compose exec app php artisan migrate
docker-compose exec app php artisan db:seed12. Acceso a la base de datos desde el host
Puedes conectarte a MySQL usando cualquier cliente (por ejemplo, DBeaver, TablePlus) con los siguientes datos:
Host:
localhostPuerto:
3306Usuario:
laraveluserContraseña:
secretBase de datos:
laravel
También puedes ingresar al contenedor de la base de datos:
docker-compose exec db mysql -u laraveluser -p
# Introduce la contraseña: secret13. Detener y eliminar los contenedores
Para detener los contenedores sin eliminarlos:
docker-compose stopPara detener y eliminar contenedores, redes y volúmenes (los datos de la BD se conservan porque usamos un volumen):
docker-compose downSi quieres eliminar también los volúmenes (y perder los datos de la BD):
docker-compose down -v14. Tips y buenas prácticas
Volúmenes para desarrollo: Hemos montado el código fuente en
/var/www/htmlcon un volumen, así que los cambios en tu máquina se reflejan instantáneamente en el contenedor.Permisos: En Linux puede haber problemas de permisos con los archivos generados por el contenedor (por ejemplo,
storageobootstrap/cache). Puedes solucionarlo ejecutando dentro del contenedor:docker-compose exec app chown -R www-data:www-data storage bootstrap/cacheOptimizar para producción: En producción, no uses volúmenes para el código; en su lugar, copia el código dentro de la imagen en el Dockerfile y usa una imagen optimizada.
Usa variables de entorno: Define todas las configuraciones sensibles en el archivo
.envy no las subas al repositorio.Añadir otros servicios: Puedes agregar fácilmente servicios como Elasticsearch, Meilisearch, Mailhog, etc., definiéndolos en el docker-compose.
15. Conclusión
Ahora tienes un entorno Docker completo para desarrollar con Laravel. Puedes compartir este repositorio con tu equipo y todos tendrán la misma configuración. Recuerda que puedes ajustar las versiones de PHP, MySQL, Nginx, etc., según tus necesidades.
Si encuentras algún error, revisa los logs con docker-compose logs -f y asegúrate de que todos los servicios estén levantados correctamente.
Enfoque A (El que puse en el tutorial): Proyecto en el Host
Cómo es: Instalas Composer en tu máquina, creas el proyecto Laravel en tu disco duro y luego montas esa carpeta dentro del contenedor con un
volumes:.Ventajas:
Rendimiento: En Windows/Mac, los volúmenes montados son más rápidos para el IDE (PHPStorm, VSCode) porque los archivos están en el sistema de archivos nativo.
Permisos: En Linux, evitas que los archivos generados dentro del contenedor (como
vendor/obootstrap/cache) pertenezcan al usuariorootowww-data, lo que te obligaría a usarsudopara borrarlos.Git: Puedes hacer
git statusdirectamente sin entrar al contenedor.
Desventaja: Necesitas tener PHP y Composer instalados en tu máquina host.
Enfoque B (El que propones): Contenedor primero, proyecto dentro
Cómo es: Solo tienes Docker instalado. Creas los contenedores vacíos y, desde dentro del contenedor
app, ejecutascomposer create-projectpara generar Laravel.Ventajas:
Cero dependencias en el host: No necesitas instalar PHP, Composer ni nada más que Docker.
Versiones exactas: La versión de PHP la dicta el contenedor, no tu sistema operativo.
Desventajas:
Permisos (el gran problema): En Linux, si ejecutas
composerdentro del contenedor, los archivos se crearán con el usuariowww-data(oroot). En tu host, esos archivos te pertenecerán a ti, pero comoroot, y no podrás editarlos con tu usuario normal sinsudo.Rendimiento: Crear el proyecto dentro de un volumen montado puede ser un poco más lento en algunos sistemas.
¿Cómo se hace exactamente el Enfoque B (el tuyo)?
Te enseño los pasos para que lo hagas como prefieres. Asumiendo que tienes la misma estructura de docker-compose.yml que te puse antes:
1. Levanta solo los contenedores (sin código aún)
Asegúrate de que la carpeta ./mi-proyecto esté vacía (o ni siquiera la crees). Ejecuta:
docker-compose up -d --buildEsto levantará los contenedores app, webserver, db, etc. La carpeta de tu host estará vacía, pero dentro del contenedor /var/www/html también estará vacía.
2. Entra al contenedor app
docker-compose exec app bash3. Dentro del contenedor, crea el proyecto Laravel
Una vez dentro del bash del contenedor, ejecuta:
composer create-project laravel/laravel .Importante: El punto (
.) al final es clave, porque estás diciendo "instálalo en la carpeta actual" (/var/www/html).
4. Ajusta el .env
Dentro del contenedor, edita el .env o cópialo desde .env.example:
cp .env.example .env
nano .env # O usa viAsegúrate de poner las credenciales de la BD como te mostré antes (DB_HOST=db).
5. Sal del contenedor y da permisos (solo si usas Linux)
Vuelve a tu terminal del host y ejecuta:
# Esto asegura que los archivos creados dentro del contenedor
# sean propiedad de TU usuario en el host, y no de 'root'
docker-compose exec app chown -R $(id -u):$(id -g) .(En Windows/Mac esto suele ser menos problemático porque Docker maneja la traducción de usuarios internamente).
6. Ejecuta las migraciones
docker-compose exec app php artisan migrateEl método "oficial" de Laravel: Laravel Sail
Curiosamente, Laravel Sail (la herramienta oficial de Laravel para Docker) combina ambos métodos:
Primero te pide que crees el proyecto con Composer en el host (Enfoque A).
Pero si no tienes Composer, te dan un comando mágico con Docker para crearlo dentro (Enfoque B):
# Así se crea un proyecto Laravel usando Docker sin tener Composer instalado:
docker run --rm \
-v $(pwd):/opt \
-w /opt \
laravelsail/php83-composer:latest \
bash -c "composer create-project laravel/laravel mi-proyecto"¿Cuál te recomiendo?
Si usas Windows o Mac: Cualquiera de los dos funciona bien. El del tutorial (Enfoque A) es más rápido para empezar.
Si usas Linux: Te recomiendo el Enfoque A (crear el proyecto en el host) para evitar dolores de cabeza con los permisos de
vendor/ystorage/.
Dicho esto, tu intuición es totalmente acertada. Hacerlo dentro del contenedor es más "puro" en términos de contenerización. Si te encuentras con problemas de permisos en Linux, ya sabes el comando chown para arreglarlo.
¿Qué sistema operativo usas? Si me dices eso, puedo darte la receta exacta para que no tengas ni un solo problema de permisos
Comentarios
Publicar un comentario