Build an image resizer with AWS S3, AWS Lambda, and Serverless

Yes Lee
7 min readDec 30, 2020

--

The CloudFormation stack template of the image-resizer.

Requirement

因為 PaaaackHiiiike 都有上傳照片的需求,所以我滿需要一個 image resizer 的,工作上曾經用過的 imgix 還滿好用的,不過一個月最少要 10 美金,所以就想說自己做一套堪用的當練習順便看看之後會花到多少錢。

TL;DR

基本上就是用 Serverless 寫一個 AWS Lambda 的 image resize function,再寫好相關的 AWS S3 trigger event 和各種 AWS 相關權限,最後 deploy 成一個 CloudFormation 然後把各種東西開好,收工!

Development

Folder structure

因為 image-resizer 會用到 S3,所以要在 local 開發的話可以用 serverless-offlineserverless-s3-local 這兩個 Serverless plugin。

首先要做個 credential 給 serverless-s3-local 用。

# ~/.aws/credentials
[s3local]
aws_access_key_id = S3RVER
aws_secret_access_key = S3RVER

接著做一份 dev 用的 serverless config。

# serverless.yml
service: image-resizer
frameworkVersion: "2"
provider:
name: aws
runtime: nodejs12.x
environment:
ENV: local
plugins:
- serverless-s3-local
- serverless-offline
custom:
s3:
host: localhost
directory: ./tmp
functions:
resize:
handler: handler.resize
events:
- s3:
bucket: images
event: s3:ObjectCreated:*
rules:
- prefix: originals/

再加上 handler.jsresize function,這邊我們是用 jimp 做 resize。

最後,再把 serverless-offline 跑起來。

{
"name": "image-resize",
"scripts": {
"dev": "serverless offline"
},
}

然後傳一張照片到 s3-local 去 trigger resize funciton。

aws --endpoint http://localhost:4569 s3 cp ./image.jpg s3://images/originals/image.jpg --profile s3local

成功囉,可以在 resizeds folder 裡看到 resized 後的 image。

Production

其實應該可以用 stage 處理不同環境,但我還是選擇先直接另外做一份 production config。

# serverless.prod.yml
service: image-resizer
frameworkVersion: "2"
provider:
name: aws
runtime: nodejs12.x
profile: yeeeeees
region: us-east-1
timeout: 20
environment:
ENV: production
iamRoleStatements:
- Effect: "Allow"
Action:
- "s3:GetObject"
Resource: "arn:aws:s3:::image-resizer/*"
- Effect: "Allow"
Action:
- "s3:PutObject"
Resource: "arn:aws:s3:::image-resizer/*"
resources:
Resources:
imageResizerBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: image-resizer
functions:
resize:
handler: handler.resize
events:
- s3:
bucket: image-resizer
event: s3:ObjectCreated:*
existing: true
rules:
- prefix: originals/

接著就可以 deploy 到 AWS 上啦。

{
"name": "2020-1224-aws-lambda-image-resize",
"scripts": {
"deploy": "serverless deploy --config serverless.prod.yml",
"logs": "serverless logs --tail --function resize"
},
}

Deploy 成功後就可以看到一堆東西XD,像是 CloudFormation。

和 Lambda function。

還有開出來的 S3 Bucket。

最後我們一樣傳一張照片到 S3 上去 trigger resize function。

aws s3 cp ./image.jpg s3://image-resizer/originals/image.jpg --profile yeeeeees

然後可以在 local 用 serverless 看 log。

也可以在 CloudWatch 上看。

以及 resize 過後的 image 啦。

成功!

Resize 一張 14.6MB 6000x4000 jpg 照片的數據如下:

  • Duration: 14231.88 ms
  • Billed Duration: 14232 ms
  • Memory Size: 1024 MB
  • Max Memory Used: 913 MB
  • Init Duration: 756.24 ms

Conclusion

  • Serverless 真的簡化了超級多 AWS 的設定細節,搞懂 config 後寫起來變得非~常簡單。
  • Performance 應該可以再調,感覺 1x 秒有點久?然後上傳再大一點的照片 memory 還會爆掉。
  • 至於費用就等之後再看囉。
  • Source code 在這邊。

--

--

Yes Lee
Yes Lee

Written by Yes Lee

Frontend Engineer in Taiwan.

No responses yet