非Docker方式部署Laravel 9应用至Google App Engine的正确步骤
无Docker部署Laravel 9到App Engine(对接Cloud Storage、Cloud SQL for MySQL)
前置准备
- 本地已有可正常运行的Laravel 9项目,完成核心业务开发
- 本地安装gcloud命令行工具,完成账号身份认证,绑定目标GCP项目
- 提前在GCP控制台开通三个服务:App Engine、Cloud SQL(MySQL 8.0/5.7均可)、Cloud Storage;创建好Cloud SQL实例、对应业务数据库、Cloud Storage存储桶,记录下Cloud SQL实例连接名、数据库账号密码、存储桶名称
- 给App Engine默认服务账号绑定两个权限:Cloud SQL客户端权限、Storage对象管理员权限,避免后续服务调用鉴权失败
本地项目配置调整
- 安装必要依赖
直接在项目根目录执行composer命令安装Storage适配所需依赖,Laravel 9自带的MySQL驱动即可满足Cloud SQL连接要求,无需额外安装数据库相关包:composer require google/cloud-storage league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies - 新增Google Storage文件系统磁盘
编辑config/filesystems.php,在disks配置段新增gcs磁盘配置,利用GCS的S3兼容接口实现对接,无需额外安装第三方文件系统适配包:
App Engine运行环境下会自动读取默认服务账号身份鉴权,GCS_KEY、GCS_SECRET字段留空即可,本地调试时再填写服务账号密钥信息。'gcs' => [ 'driver' => 's3', 'key' => env('GCS_KEY'), 'secret' => env('GCS_SECRET'), 'region' => env('GCS_REGION', 'auto'), 'bucket' => env('GCS_BUCKET'), 'endpoint' => env('GCS_ENDPOINT', 'https://storage.googleapis.com'), 'use_path_style_endpoint' => true, 'throw' => false, ], - 调整数据库连接逻辑适配Cloud SQL
编辑config/database.php,保留MySQL连接默认配置即可,后续通过环境变量传入UNIX Socket路径,实现App Engine和Cloud SQL的内网通信,无需公网连接:'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], - 适配App Engine只读文件系统
App Engine标准环境运行目录为只读,仅/tmp目录可写入,需要在app/Providers/AppServiceProvider.php的boot方法中添加临时路径配置,避免缓存、视图写入报错:
注意生产环境不要用file驱动存储session,因为public function boot() { if (env('APP_ENV') === 'production') { config()->set('view.compiled', '/tmp/views'); config()->set('cache.stores.file.path', '/tmp/cache'); if (!is_dir('/tmp/views')) mkdir('/tmp/views', 0755, true); if (!is_dir('/tmp/cache')) mkdir('/tmp/cache', 0755, true); } }/tmp目录会随实例重启清空,建议改用cookie或database驱动。 - 生成应用密钥
如果本地还没生成APP_KEY,执行php artisan key:generate,记录生成的密钥后续填入环境变量。
编写App Engine部署配置
这里使用App Engine标准环境官方维护的PHP运行时,无需编写Dockerfile,完全满足无Docker部署要求
在项目根目录新建app.yaml配置文件,内容参考如下,替换成你自己的资源参数即可:
runtime: php81 env: standard handlers: # 静态资源直接由App Engine边缘节点返回,不经过PHP解析,提升访问性能 - url: /(.*\.(gif|png|jpg|jpeg|css|js|ico|svg|woff|woff2|ttf|map))$ static_files: public/\1 upload: public/.*\.(gif|png|jpg|jpeg|css|js|ico|svg|woff|woff2|ttf|map)$ # 其余请求统一转发到Laravel入口 - url: /.* script: auto # 环境变量配置 env_variables: APP_ENV: production APP_LOG: errorlog APP_KEY: 替换为你本地生成的APP_KEY APP_DEBUG: false APP_URL: https://替换为你的项目ID.uc.r.appspot.com DB_CONNECTION: mysql # Cloud SQL UNIX Socket固定路径格式,后缀替换为你的实例连接名 DB_SOCKET: /cloudsql/替换为你的Cloud SQL实例连接名 DB_DATABASE: 替换为你创建的数据库名 DB_USERNAME: 替换为数据库账号 DB_PASSWORD: 替换为数据库密码 FILESYSTEM_DISK: gcs GCS_BUCKET: 替换为你创建的存储桶名称 SESSION_DRIVER: cookie CACHE_DRIVER: file # 挂载Cloud SQL UNIX Socket到运行环境 beta_settings: cloud_sql_instances: 替换为你的Cloud SQL实例连接名
在项目根目录新建.gcloudignore文件,排除不需要上传的目录,减少部署包体积,内容参考:
/vendor /node_modules .env .git .gitignore storage/logs/* storage/framework/cache/* storage/framework/sessions/* storage/framework/views/*
执行部署
- 本地执行
php artisan config:cache生成配置缓存,优化线上启动速度 - 终端切换到项目根目录,执行部署命令:
gcloud app deploy,等待部署进度完成 - 部署完成后执行
gcloud app browse可直接打开线上站点地址 - 执行线上初始化操作:
gcloud app exec php artisan migrate --force,完成数据库表结构迁移,有初始化种子数据的话可以追加--seed参数 - 功能验证:测试页面访问是否正常、文件上传是否能同步到Cloud Storage、数据库读写操作是否正常
常见问题排查
- 数据库连接失败:先检查App Engine服务账号是否绑定了Cloud SQL客户端权限,确认
beta_settings里的实例连接名和DB_SOCKET配置一致,数据库账号密码有对应库的操作权限,Cloud SQL实例和App Engine属于同一项目 - 文件上传失败:检查服务账号是否有Storage存储桶的写入权限,确认存储桶名称配置正确,GCS端点配置没有写错
- 页面报500权限错误:检查是否把视图、缓存的写入路径都配置到了
/tmp目录,对应目录是否有自动创建逻辑 - 静态资源404:检查
app.yaml里的静态资源路径映射规则是否正确,所有静态资源是否都存放在public目录下
内容的提问来源于stack exchange,提问作者Hakeem.D
相关产品推荐
相关产品推荐

