在 AWS Serverless 平台上部署 Laravel (laravel-mix) 应用程序
Posted
技术标签:
【中文标题】在 AWS Serverless 平台上部署 Laravel (laravel-mix) 应用程序【英文标题】:Deploying Laravel (laravel-mix) application on AWS Serverless platform 【发布时间】:2021-03-23 11:40:24 【问题描述】:我正在尝试在 AWS 无服务器平台上部署我的 Laravel 应用程序,我在我的 laravel-mix 中使用动态导入和代码拆分来编译资产,执行此操作我按照bref package 文档中的步骤进行操作我按照指示安装了所需的库,我还将我的公共目录与我的 s3 存储桶同步
npm run prod
aws s3 sync public/ s3://<bucket-name>/ --delete --exclude index.php
并将我的.env
文件配置为:
MIX_ASSET_URL=https://<bucket-name>.s3.amazonaws.com
ASSET_URL=https://<bucket-name>.s3.amazonaws.com
接下来我将blade
文件配置为:
<script src=" asset('nits-assets/js/app.js') "></script>
我的webpack.mix.js
文件有:
const mix = require('laravel-mix')
const webpack = require('webpack');
const ASSET_URL = process.env.ASSET_URL + "/";
mix.js('resources/js/app.js', 'public/nits-assets/js')
.postCss('resources/sass/app.css', 'public/nits-assets/css', [
require("tailwindcss"),
])
.webpackConfig(
output:
chunkFilename: 'nits-assets/chunks/[name].[contenthash].js',
publicPath: ASSET_URL
,
resolve:
symlinks: false,
alias:
NitsModels: path.resolve(__dirname, 'Models'),
,
,
plugins: [
new webpack.DefinePlugin(
"process.env.ASSET_PATH": JSON.stringify(ASSET_URL)
)
],
).sourceMaps().version();
由于我将代码拆分为块,因此在获取块时遇到了麻烦,我最初的 app.js
文件从 s3 存储桶加载,但为了加载块,它尝试通过公共目录获取。
如何配置我的 laravel-mix
以从与我的公共目录同步的 s3 存储桶加载块?
编辑:
按照答案中的建议,我更改了 serverless.yml,它看起来像这样:
service: laravel
provider:
name: aws
# The AWS region in which to deploy (us-east-1 is the default)
region: ap-south-1
# The stage of the application, e.g. dev, production, staging… ('dev' is the default)
stage: dev
runtime: provided.al2
environment:
AWS_BUCKET: # environment variable for Laravel
Ref: Storage
iamRoleStatements:
# Allow Lambda to read and write files in the S3 buckets
- Effect: Allow
Action:
- s3:PutObject
- s3:ListBucket
- s3:GetObject
Resource:
- Fn::GetAtt: Storage.Arn # the storage bucket
- Fn::Join: [ '', [ Fn::GetAtt: Storage.Arn, '/*' ] ] # everything in the storage bucket
resources:
Resources:
Storage:
Type: AWS::S3::Bucket
package:
# Directories to exclude from deployment
exclude:
- node_modules/**
- public/storage
- resources/assets/**
- storage/**
- tests/**
functions:
# This function runs the Laravel website/API
web:
handler: public/index.php
timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
layers:
- $bref:layer.php-74-fpm
events:
- httpApi: '*'
# This function lets us run artisan commands in Lambda
artisan:
handler: artisan
timeout: 120 # in seconds
layers:
- $bref:layer.php-74 # PHP
- $bref:layer.console # The "console" layer
plugins:
# We need to include the Bref plugin
- ./vendor/bref/bref
现在我得到了:
发生错误:ArtisanLambdaFunction - 属性变量的值必须是具有字符串(或简单类型)属性的对象。
编辑 2:
问题在于 serverless.yml 中的 indent(tab) 配置:
environment:
AWS_BUCKET: # environment variable for Laravel
Ref: Storage
iamRoleStatements:
# Allow Lambda to read and write files in the S3 buckets
- Effect: Allow
Action: s3:*
但现在有一个单独的问题:
错误:CloudFormation 模板无效:模板错误:每个 Fn::GetAtt 对象都需要两个非空参数,资源名称和资源属性
【问题讨论】:
之前没用过这个,但是在解析配置的时候某个地方,它期望对象中的所有值必须是简单类型或字符串,它找到了另一个对象,数组或函数,不能应用于流程。 它可以在属性Resource: - Fn::GetAtt
上返回一个对象而不是简单类型的字符串吗?
@KeitelDOG 我修复了前一个问题,但现在我遇到了Error: The CloudFormation template is invalid: Template error: every Fn::GetAtt object requires two non-empty parameters, the resource name and the resource attribute
问题你能帮我解决这个问题吗?
Fn::GetAtt
需要 2 个参数。格式可以像Fn::GetAtt: [ logicalNameOfResource, attributeName ]
。官方文档:docs.amazonaws.cn/en_us/AWSCloudFormation/latest/UserGuide/… 包含所需属性的资源的逻辑名称(也称为逻辑 ID)。您想要其值的资源特定属性的属性名称。有关该资源类型可用属性的详细信息,请参阅资源的参考页面。
检查模板结构。真的有resources.Resources吗?也许您只想指定 Resources.Storage [type: AWS::S3::Bucket , ...] 并在 Fn::GetAtt: [ "Storage", "BucketName" ]
或任何其他属性名称中指定 Bucket 的有效属性。 Fn::GetAtt
是一个函数,它在模板中获取资源的属性,以使它们可重用。因此,我认为它必须存在于您的模板中,隐含地来自 AWS 模板或您的语法。 S3 存储桶属性:docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…
【参考方案1】:
403 错误表明您未经授权或存在某种权限错误。
基于此页面:
https://bref.sh/docs/frameworks/laravel.html
您能否确认您已为 lambda 设置适当的权限以从您使用的 s3 存储桶读取和写入?
...
provider:
...
environment:
AWS_BUCKET: # environment variable for Laravel
Ref: Storage
iamRoleStatements:
# Allow Lambda to read and write files in the S3 buckets
- Effect: Allow
Action: s3:*
Resource:
- Fn::GetAtt: Storage.Arn # the storage bucket
- Fn::Join: ['', [Fn::GetAtt: Storage.Arn, '/*']] # everything in the storage bucket
resources:
Resources:
Storage:
Type: AWS::S3::Bucket
文档继续说您必须在 config/filesystems.php 中添加来自以下 sn-p 的令牌行。你这样做了吗?
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'token' => env('AWS_SESSION_TOKEN'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
我不使用 Laravel,所以上述建议只是基于查看您的错误并阅读文档。但如果你提供更多信息,我很乐意看看
【讨论】:
我已经添加了 serverless.yml 配置内容。现在我收到An error occurred: ArtisanLambdaFunction - Value of property Variables must be an object with String (or simple type) properties.
@NitishKumar 错误解释了问题所在 - 检查您的属性变量。
这个错误是在我配置了我的serverless.yml
文件之后出现的。我是新手,不知道如何解决。在此错误之前,我遇到了An error occurred: WebLambdaFunction - Value of property Variables must be an object with String (or simple type) properties.
,我点击了这个链接:forum.serverless.com/t/… 现在错误出现在ArtisanLambdaFunction
上找不到更好的解决方案。
@NitishKumar 该错误表明您的变量必须是对象或字符串。只需逐行浏览您的文件,检查每个条目的格式是否不正确。跨度>
@NitishKumar 请参阅 GetAtt 的文档... 如果您使用的是完整形式,则语法为 Fn::GetAtt: [LogicalNameOfResource, attributeName] ... 如果您使用的是简短形式你应该使用 !GetAtt以上是关于在 AWS Serverless 平台上部署 Laravel (laravel-mix) 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
真送礼物1 分钟 Serverless 极速部署盲盒平台,自己部署自己抽!