使用Gitlab CI + S3 + Cloudfront佈署靜態網站
AWS前置設定
建立IAM User
這個IAM User之後要提供給Gitlab CI使用
讓Gitlab CI可以自動將web上傳至s3
並且清除Cloudfront cache
以下為參考permission json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"cloudfront:GetInvalidation",
"cloudfront:CreateInvalidation"
],
"Resource": "*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:PutObject",
"s3:ListBucket",
"s3:GetObjectAcl",
"s3:PutBucketAcl",
"s3:GetObject",
"s3:PutObjectAcl",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::web-bucket",
"arn:aws:s3:::web-bucket/*"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets"
],
"Resource": "*"
}
]
}
設定S3 bucket
建立一個bucket
將「封鎖所有公開存取權」功能「關閉」
物件擁有權設定為「物件寫入器」
並啟用靜態網站託管
Gitlab CI設定
設定CI/CD Variable
- Key: AWS_SHARED_CREDENTIALS_FILE
- Type: File
- Value: 設定前面的IAM key, 用來讓Gitlab CI可以更新S3及設定CloudFront, 格式如下
[default]
aws_access_key_id = aws_access_key_id
aws_secret_access_key = aws_secret_access_key
設定.gitlab-ci.yml
variables:
WEB_DOMAIN: example.com
stages:
- test
- build
- deploy
# build nuxt並存至gitlab artifact
build:
stage: build
image: node:20
cache:
paths:
- frontend/node_modules
only:
variables:
- $CI_COMMIT_TAG =~ /build/
script:
- cd $CI_PROJECT_DIR/frontend
- yarn
- yarn generate
- cp -r $CI_PROJECT_DIR/frontend/.output/public $CI_PROJECT_DIR/web-artifact
artifacts:
name: $CI_COMMIT_SHORT_SHA
expire_in: 1 hour
paths:
- $CI_PROJECT_DIR/web-artifact
# 將前面build好的nuxt site上傳至指定s3 bucket中
deploy:
stage: deploy
image:
name: amazon/aws-cli
entrypoint: [ "" ]
variables:
BUCKET_NAME: my-web-bucket
only:
variables:
- $CI_COMMIT_TAG =~ /deploy/
dependencies:
- build
script:
- aws s3 rm s3://$BUCKET_NAME/ --recursive
- |
aws s3 sync ./web-artifact s3://$BUCKET_NAME/ \
--acl public-read \
--cache-control "max-age=31536000"
測試
透過git tag的方式觸發build/deploy job
並確認網站是否能夠正確上傳至s3
完成後
可以先上s3 bucket確認是否有檔案
並且到s3的靜態網站託管設定中取得網站endpoint
直接在瀏覽器存取看看
基本上有看到網站正常呈現就代表成功
透過Cloudfront對網站進行cache
先建立自訂的s3-website policy
Headers設定
- Origin
- x-method-override
- Referer
- x-http-method
- x-http-method
並啟用br/gzip壓縮
因為後續每次更新網站都會自動使用cloudfront invalidation
因此TTL可以直接設定成一年(31536000秒)
建立distribution
origin domain選擇其面建立的web s3 bucket
cache的部份
建立完成之後要等它佈署一下
佈署完成後
直接用瀏覽器存取cloudfront的endpoint
確認有看到網站就代表成功
如果要確認是否有cache成功
可以開啟chrome developer tool查看network
資源請求如果response header有X-Cache: Hit from cloudfront就代表cache成功
Gitlab CI調整在更新後執行CloudFront invalidation
因為cloud front本身會進行cache
如果再佈署網站沒有清除cache的話會吃到舊的資源
因此需要再調整.gitlab-ci.yml的deploy job
在網站更新至s3後清除cache
aws cloudfront create-invalidation \
--distribution-id $CLOUDFRONT_DISTRIBUTION_ID \
--paths "/*"
若要額外自訂invalidation規則
可參考此文件
使用自訂domain
通常我們不會直接使用cloudfront的預設domain
因為他是無意義的名稱
因此我們需要設定自訂網域
AWS Certificate Manger設定
前往AWS Certificate Manger設定頁面
region選擇us-east-1(virginia)
因為cloudfront自訂網域只接受us-east-1的的憑證
接著請求一個公有憑證
驗證方式依照需求
這邊使用DNS驗證
DNS設定
憑證建立完成之後
會產生一個驗證個CNAME規則
至設定DNS好規則後即可
另外也需要使用CNAME規則將自己的網域指向cloudfront的原始網域
需要等待一下讓Certificate Manger驗證
等驗證成功後
即可進行下一步至Cloudfront設定
Cloudfront設定調整
前往cloudfront設定備用網域
Done!
接著等待cloudfront更新完成即可