Error de permisos en Laravel con Docker (Linux)
1. Descripción del problema
Tras instalar Laravel en un entorno Linux con Docker y eliminar el index.php de pruebas, al acceder a http://localhost:8080 aparece un error de permisos denegados.
Aunque los contenedores están levantados y la conexión a base de datos funcionaba con el index.php previo, al crear el volumen y montar el proyecto Laravel en src/ el servidor ya no puede leer o escribir en los archivos.
Contexto típico:
- Volumen bind:
./srcen el host montado como/var/www/htmldentro del contenedor. - Servicios habituales:
php(php-fpm) ynginx. - El contenedor
phpnecesita leer y escribir en/var/www/html, ynginxleerlo para servir.
Causa más común:
Desajuste de propietarios y permisos entre el host y el contenedor. Dentro del contenedor, los procesos suelen correr como www-data:www-data. En el host, los archivos pertenecen a tu usuario. Esto rompe la escritura/lectura cuando se monta el volumen.
2. Objetivo
- Hacer que el usuario interno del contenedor (
www-data) tenga permisos correctos sobre/var/www/html. - Mantener la edición fluida en el host con tu usuario.
- Evitar errores 403/500 por permisos y problemas de cache/logs de Laravel.
3. Requisitos previos
- Docker y Docker Compose funcionando.
-
Estructura del proyecto similar a:
. ├─ docker-compose.yml ├─ src/ # código Laravel montado al contenedor en /var/www/html └─ ... -
Conocer el nombre del contenedor PHP (por ejemplo
laravel_app-php-1). Puedes listar con:docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" -
Si no conoces puedes utilizar
docker composey el nombre del servicio:docker compose exec php bash
4. Solución paso a paso
Paso 1. Ajustar permisos dentro del contenedor PHP
-
Entrar en el contenedor PHP:
o bien:docker exec -it laravel_app-php-1 bashdocker-compose exec php bash -
Asignar propietario y grupo
www-dataa la webroot:chown -R www-data:www-data /var/www/html -
Establecer permisos seguros de lectura/ejecución:
chmod -R 755 /var/www/html
Resultado esperado
Resultado esperado: localhost:8080 vuelve a servir la aplicación, porque www-data puede leer el código. Si usas Laravel, recuerda que storage/ y bootstrap/cache requieren escritura; este ajuste se verá en el Paso 3.
Paso 2. Permitir edición desde el host sin errores de permisos
Tras el Paso 1 puedes encontrar que tu usuario en el host no puede editar algunos archivos en src/. Para que tanto tu usuario como el usuario www-data del contenedor trabajen sin pisarse:
-
Añade tu usuario al grupo
www-dataen el host:sudo usermod -aG www-data TU_USUARIOpor eejmplo si tu usuario es:
profesor:sudo usermod -aG www-data profesor -
Reinicia la sesión para aplicar el cambio de grupos: cierra sesión y vuelve a entrar, o reinicia la máquina. Verifica:
groups TU_USUARIO # Debería aparecer 'www-data' -
En el host, ajusta propietario y grupo de
src/:sudo chown -R TU_USUARIO:www-data src -
Permisos de colaboración (lectura y escritura para usuario y grupo):
sudo chmod -R 775 src
Permisos locales
Con esto, tu usuario edita archivos en src/ sin fricciones y el contenedor (grupo www-data) también tiene permisos de escritura cuando lo necesite.
Paso 3. Directorios que Laravel necesita con escritura
Laravel requiere escritura en:
storage/bootstrap/cache/
Si no existen o no tienen permisos adecuados, alinea permisos explícitamente:
Dentro del host:
sudo chown -R TU_USUARIO:www-data src/storage src/bootstrap/cache
sudo chmod -R 775 src/storage src/bootstrap/cache
Dentro del contenedor PHP (opcional, por coherencia):
primero entra en el contenedor de PHP:
docker exec -it laravel_app-php-1 bash
docker compose exec php bash
Para modificar los permisos en el contenedor ejecuta:
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
chmod -R 775 /var/www/html/storage /var/www/html/bootstrap/cache
5. Comprobaciones rápidas
- Navegador:
http://localhost:8080carga la página de inicio de Laravel. -
Logs:
- Nginx: revisa el contenedor de nginx si hay 403/502.
- PHP/Laravel:
storage/logs/laravel.log.
-
Cache de Laravel:
docker exec -it laravel_app-php-1 bash -lc 'php artisan optimize:clear'o bien:
docker compose exec php bash -lc 'php artisan optimize:clear'
6. Notas y buenas prácticas
- Evita
chmod -R 777. Usa775para colaboración usuario-grupo y restringe a lo necesario. - Si los contenedores definen un
user:con UID/GID específico, alinea el UID/GID dewww-datacon el de tu usuario del host o usa variables de entorno para mapearlos. - Mantén el volumen solo para el código. Para datos persistentes de la app (cache, sesiones, logs) considera volúmenes gestionados por Docker.
- Si cambiaste nombres de servicios, ajusta el nombre del contenedor en los comandos
docker exec. - Cada vez que añadas tu usuario a un grupo, reinicia sesión para que surta efecto.
7. Conclusión
Esta es la solución encontrada cuando una vez instalados los contenedores Docker en Linux, al montar el código fuente Laravel desde el host, el servidor web no podía leer los archivos por problemas de permisos.
Otra solución posible es ajustar los UID/GID de los usuarios dentro del contenedor para que coincidan con los del host, pero esto puede complicar la configuración y mantenimiento ya que sería necesario modificar el Dockerfile o usar variables de entorno. Est solución la dejo para el futuro, ya que con los cursos en marcha no creo que sea buena idea modificar los fichjeros de los contenedores.
8. Resumen
- Dentro del contenedor PHP:
docker exec -it laravel_app-php-1 bash
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html
- En el host:
sudo usermod -aG www-data TU_USUARIO
# cerrar sesión y volver a entrar
groups TU_USUARIO
sudo chown -R TU_USUARIO:www-data src
sudo chmod -R 775 src
- Directorios clave de Laravel:
sudo chown -R TU_USUARIO:www-data src/storage src/bootstrap/cache
sudo chmod -R 775 src/storage src/bootstrap/cache
docker exec -it laravel_app-php-1 bash -lc 'php artisan optimize:clear'