laravel-admin 不能直接用 composer create-project 启动就完事——它依赖 Laravel 框架本身,且容器内数据库、Web 服务、权限、缓存等必须协同就位;docker-compose.yml 必须定义 PHP-FPM、Nginx、MySQL 三个基础服务,DB_HOST 必须设为 mysql(服务名),php artisan admin:install 前需确保 migrate、storage:link 等前置命令已成功执行。

laravel-admin 不能直接用 composer create-project 启动就完事——它依赖 Laravel 框架本身,且容器内数据库、Web 服务、权限、缓存等必须协同就位。跳过容器编排直接“安装”只会卡在 php artisan admin:install 报错或白屏。
docker-compose.yml 必须定义三个基础服务
Laravel-Admin 不是独立应用,而是 Laravel 的扩展包,所以它的容器化前提是:PHP-FPM(跑 Laravel)、Nginx(转发请求)、MySQL(存配置/用户/菜单)。三者缺一不可,且网络互通。
-
app服务负责运行 PHP 和 Artisan 命令,需挂载代码、安装依赖、暴露9000端口供 Nginx FastCGI 调用 -
nginx服务必须用fastcgi_pass app:9000(不是localhost:9000),否则 502 -
mysql服务的MYSQL_DATABASE值要和.env中的DB_DATABASE完全一致,大小写敏感
常见错误现象:SQLSTATE[HY000] [1045] Access denied for user 'root'@'app' —— 这说明 Nginx 或 PHP 容器尝试用 root 连 MySQL,但没配对 MYSQL_ROOT_PASSWORD;或更常见的是,app 容器启动早于 mysql,连接失败后没重试机制。
.env 里 DB_HOST 必须写成服务名,不是 localhost
Docker 内部网络靠服务名解析,localhost 在 app 容器里指向自己,不是 MySQL。不改这个,php artisan migrate 必然失败。
- ✅ 正确:
DB_HOST=mysql(与docker-compose.yml中 mysql 服务名完全一致) - ❌ 错误:
DB_HOST=127.0.0.1、DB_HOST=localhost、DB_HOST=db(除非你把服务起名叫db) - 还要同步检查:
REDIS_HOST=redis(如果启用了缓存)、SESSION_DRIVER=redis(若用 Redis 存 session)
执行迁移前,先进入容器验证连通性:docker-compose exec app bash -c "ping -c 1 mysql" 和 docker-compose exec app php -r "var_dump(@mysqli_connect('mysql', 'root', 'secret', 'laravel_admin'));"。
php artisan admin:install 要在容器内执行,且依赖已就绪
这个命令不是“一键安装”,它会:建表、发布静态资源、生成管理员账号、清空 config cache。任一环节断链都会中断。
- 必须先确保:
composer install --no-dev --optimize-autoloader已在app容器内完成 - 必须先确保:
php artisan migrate成功(否则表不存在,admin:install直接抛异常) - 必须先确保:
php artisan storage:link已执行(否则上传头像、文件会 500) - 推荐顺序执行(在
app容器内):php artisan key:generatephp artisan migrate --forcephp artisan storage:linkphp artisan admin:install
如果提示 Class 'Encore\Admin\Form' not found,说明 composer install 没跑成功,或 vendor 没挂载进容器(检查 volumes 是否覆盖了 ./vendor)。
真正容易被忽略的点是:Laravel-Admin 的前端资源(public/vendor/admin)默认由 php artisan vendor:publish 发布,但该命令在多阶段构建镜像时可能被跳过;若用 volume 挂载源码,又没手动运行发布命令,Nginx 就会返回 404 静态文件。别只盯着 PHP 报错,浏览器 F12 看 Network 标签里是不是一堆 GET /vendor/admin/xxx.js net::ERR_ABORTED 404。


















