บันทึก
สาขาหลักในปัจจุบันมีการปรับใช้อะตอมอัลฟ่าตัวอย่าง
สำหรับการเปิดตัวที่มีเสถียรภาพครั้งล่าสุดลองดูสาขาv0.xโปรดดูโพสต์บล็อกของเรา
หรือดูรีวิวล่าสุดสำหรับข้อมูลเพิ่มเติม:
โมดูล Terraform ที่ไม่รวมศูนย์สำหรับการโฮสต์ตัวเอง next.js ไซต์ Serverless บน AWS Lambda
คุณสมบัติบางอย่างยังอยู่ระหว่างการพัฒนานี่คือรายการของคุณสมบัติที่ได้รับการสนับสนุนในปัจจุบันและสิ่งที่เราวางแผนที่จะนำมาซึ่งการเผยแพร่ครั้งต่อไป:
v0.15+โมดูล Terraform Next.js ได้รับการออกแบบให้เป็นแอพ AWS เต็มสแต็ก มันขึ้นอยู่กับบริการ AWS หลายบริการและเชื่อมต่อพวกเขาให้ทำงานเป็นแอปพลิเคชันเดียว:

คุณควรติดตั้งเครื่องมือต่อไปนี้:
หมายเหตุ: นอกจากนี้เรายังสมมติว่าที่นี่คุณมีโซนที่โฮสต์ Route53 ที่เกี่ยวข้องกับบัญชี AWS ของคุณแล้ว
นี่เป็นข้อกำหนดในขั้นตอนการแสดงตัวอย่างของการปรับใช้อะตอมซึ่งการปรับใช้แต่ละครั้งจะได้รับการกำหนดโดเมนย่อยที่ไม่ซ้ำกัน มันจะเปลี่ยนการปรับใช้อะตอมโดยทั่วไป
โมดูล Terraform มีระบบที่ใช้ในภายหลังสำหรับการสร้างการปรับใช้ใหม่และการจัดการนามแฝง (โดเมน) สำหรับแอป Next.js ของคุณ การสร้างสแต็ก Terraform เป็นสิ่งจำเป็นเฉพาะในการตั้งค่าเริ่มต้นและสร้างทรัพยากรทั่วโลก (การแจกแจงแบบ CloudFront, DynamoDB Tables, S3 Storage) ที่ใช้สำหรับการจัดการคำขอเข้ามาในเว็บไซต์ของคุณ
สร้างไฟล์ main.tf ใหม่ในโฟลเดอร์ว่าง (หรือเพิ่มลงในสแต็ก Terraform ที่มีอยู่ของคุณ) และเพิ่มเนื้อหาต่อไปนี้:
terraform {
required_providers {
aws = {
source = " hashicorp/aws "
version = " ~> 4.0 "
}
}
}
# Main region where the resources should be created in
# Should be close to the location of your viewers
provider "aws" {
region = " us-west-2 "
}
# Provider used for creating the Lambda@Edge function which must be deployed
# to us-east-1 region (Should not be changed)
provider "aws" {
alias = " global_region "
region = " us-east-1 "
}
# ##########
# Variables
# ##########
variable "custom_domain" {
description = " Your custom domain "
type = string
default = " example.com "
}
# Assuming that the ZONE of your domain is already available in your AWS account (Route 53)
# https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/AboutHZWorkingWith.html
variable "custom_domain_zone_name" {
description = " The Route53 zone name of the custom domain "
type = string
default = " example.com. "
}
# #######
# Locals
# #######
locals {
# A wildcard domain(ex: *.example.com) has to be added when using atomic deployments:
aliases = [ var . custom_domain , " *. ${ var . custom_domain } " ]
}
# ######################
# Route53 Domain record
# ######################
# Get the hosted zone for the custom domain
data "aws_route53_zone" "custom_domain_zone" {
name = var . custom_domain_zone_name
}
# Create a new record in Route 53 for the domain
resource "aws_route53_record" "cloudfront_alias_domain" {
for_each = toset (local . aliases )
zone_id = data . aws_route53_zone . custom_domain_zone . zone_id
name = each . key
type = " A "
alias {
name = module . tf_next . cloudfront_domain_name
zone_id = module . tf_next . cloudfront_hosted_zone_id
evaluate_target_health = false
}
}
# #########
# SSL Cert
# #########
# Creates a free SSL certificate for CloudFront distribution
# For more options (e.g. multiple domains) see:
# https://registry.terraform.io/modules/terraform-aws-modules/acm/aws/
module "cloudfront_cert" {
source = " terraform-aws-modules/acm/aws "
version = " ~> 3.0 "
domain_name = var . custom_domain
zone_id = data . aws_route53_zone . custom_domain_zone . zone_id
subject_alternative_names = slice (local . aliases , 1 , length (local . aliases ))
wait_for_validation = true
tags = {
Name = " CloudFront ${ var . custom_domain } "
}
# CloudFront works only with certs stored in us-east-1
providers = {
aws = aws.global_region
}
}
# #########################
# Terraform Next.js Module
# #########################
module "tf_next" {
source = " milliHQ/next-js/aws "
version = " 1.0.0-canary.4 "
cloudfront_aliases = local . aliases
cloudfront_acm_certificate_arn = module . cloudfront_cert . acm_certificate_arn
deployment_name = " atomic-deployments "
enable_multiple_deployments = true
multiple_deployments_base_domain = " *. ${ var . custom_domain } "
providers = {
aws.global_region = aws.global_region
}
}
# ########
# Outputs
# ########
output "api_endpoint" {
value = module . tf_next . api_endpoint
}
output "api_endpoint_access_policy_arn" {
value = module . tf_next . api_endpoint_access_policy_arn
}หากต้องการสร้างทรัพยากรในบัญชี AWS ของคุณให้เรียกใช้คำสั่งต่อไปนี้:
terraform init # Only needed on the first time running Terraform
terraform plan # (Optional) See what resources Terraform will create
terraform apply # Create the resources in your AWS account
> Apply complete !
>
> Outputs:
>
> api_endpoint = " https://<api-id>.execute-api.us-west-2.amazonaws.com "
> api_endpoint_access_policy_arn = " arn:aws:iam::123456789012:policy/access-api " api_endpoint ถูกใช้ในภายหลังโดยเครื่องมือ CLI เพื่อสร้างการปรับใช้ใหม่
ด้วยนโยบาย api_endpoint_access_policy_arn AWS คุณสามารถสร้างผู้ใช้ใหม่ (และกำหนดนโยบายนั้น) ที่สามารถใช้เครื่องมือ CLI tf-next แต่ไม่สามารถเข้าถึงทรัพยากรอื่น ๆ ภายในบัญชี AWS ของคุณได้
หลังจากการปรับใช้ที่ประสบความสำเร็จแอป Next.js ของคุณจะเปิดเผยต่อสาธารณะที่โดเมนย่อย CloudFront จากเอาต์พุต cloudfront_domain_name
สำหรับการสร้างและปรับใช้แอป next.js ไปยังระบบเราสร้างเครื่องมือ CLI ที่เรียกว่า tf-next
เป็นแพ็คเกจ NPM ที่สามารถติดตั้งได้ด้วย:
npm i -g tf-next@canary ต่อไปเราจำเป็นต้องสร้างต่อไป js เพื่อให้สามารถทำงานในสภาพแวดล้อมที่ไม่มีเซิร์ฟเวอร์ (ด้วย AWS Lambda) สิ่งนี้ถูกเก็บถาวรโดยใช้ tf-next build ในไดเรกทอรีเดียวกันกับที่แอป next.js ของคุณตั้งอยู่ (ตรงกับที่ package.json หรือ next.config.js อยู่):
tf-next build
> All serverless functions created in: 20.791ms
> 1752924 total bytes
> Build successful!
ตอนนี้ปรับใช้แอป Next.js โดยเรียกใช้ tf-next deploy จากไดเรกทอรีเดียวกัน คำสั่งการปรับใช้สื่อสารผ่าน API ที่ปลอดภัย (และรับรองความถูกต้องด้วยข้อมูลรับรอง AWS ของคุณ) ด้วยโมดูล Terraform
ในการบอกคำสั่งที่จะปรับใช้แอพต้องให้ธงเพิ่มเติม --endpoint ซึ่งควรใช้ค่าจากเอาต์พุต api_endpoint จากขั้นตอน terraform apply :
tf-next deploy --endpoint https://<api-id>.execute-api.us-west-2.amazonaws.com
> Available at: https://3edade7a2bf7bb0343699af6b851bbfa.example.com/
ตอนนี้การปรับใช้ตัวอย่างสามารถเข้าถึงได้โดย URL ที่แสดง
เพื่อให้การปรับใช้พร้อมใช้งานจาก URL ที่อ่านได้มากขึ้นคุณสามารถใช้คำสั่งย่อย tf-next alias :
tf-next alias set my-app.example.com 3edade7a2bf7bb0343699af6b851bbfa.example.com
> Available at: https://my-app.example.com/
สำหรับรายการคำสั่งที่มีอยู่ทั้งหมดที่สามารถใช้กับ tf-next ตรวจสอบการอ้างอิงคำสั่ง
| ชื่อ | รุ่น |
|---|---|
| รูปปั้น | > = 0.15 |
| aws | > = 4.8 |
| ชื่อ | รุ่น |
|---|---|
| aws | > = 4.8 |
| ชื่อ | คำอธิบาย | พิมพ์ | ค่าเริ่มต้น | ที่จำเป็น |
|---|---|---|---|---|
| cloudfront_acm_certificate_arn | ใบรับรอง ACM ARN สำหรับ custom_domain | string | null | เลขที่ |
| Cloudfront_aliases | นามแฝงสำหรับ custom_domain | list(string) | [] | เลขที่ |
| cloudfront_cache_key_headers | ปุ่มส่วนหัวที่ควรใช้ในการคำนวณคีย์แคชใน CloudFront | list(string) | - | เลขที่ |
| CloudFront_Create_Distribution | ควบคุมว่าควรสร้างการแจกแจงแบบเมฆเมฆหลักหรือไม่ | bool | true | เลขที่ |
| Cloudfront_external_arn | เมื่อใช้การแจกแจงแบบเมฆภายนอกให้ ARN | string | null | เลขที่ |
| Cloudfront_external_id | เมื่อใช้การกระจาย CloudFront ภายนอกให้ ID | string | null | เลขที่ |
| cloudfront_minimum_protocol_version | โปรโตคอล SSL รุ่นต่ำสุดที่คุณต้องการให้ CloudFront ใช้สำหรับการเชื่อมต่อ HTTPS หนึ่งใน SSLV3, TLSV1, TLSV1_2016, TLSV1.1_2016, TLSV1.2_2018 หรือ TLSV1.2_2019 | string | "TLSv1" | เลขที่ |
| cloudfront_origin_request_policy | ID ของนโยบายการร้องขอที่กำหนดเองที่แทนที่นโยบายเริ่มต้น (AllViewer) สามารถกำหนดเองหรือจัดการได้ | string | null | เลขที่ |
| CloudFront_price_class | คลาสราคาสำหรับการแจกแจงแบบ CloudFront (Main & Proxy Config) หนึ่งใน priceclass_all, priceclass_200, priceclass_100 | string | "PriceClass_100" | เลขที่ |
| cloudfront_response_headers_policy | ID ของนโยบายส่วนหัวการตอบสนอง สามารถกำหนดเองหรือจัดการได้ ค่าเริ่มต้นว่างเปล่า | string | null | เลขที่ |
| CloudFront_webacl_id | WebACL2 ARN หรือ WebACL ID เสริมที่เป็นตัวเลือกเพื่อเชื่อมโยงกับการกระจาย CloudFront | string | null | เลขที่ |
| create_image_optimization | การควบคุมว่าควรสร้างทรัพยากรสำหรับการสนับสนุนการเพิ่มประสิทธิภาพรูปภาพหรือไม่ | bool | true | เลขที่ |
| debug_use_local_packages | ใช้แพ็คเกจที่สร้างขึ้นในพื้นที่แทนที่จะดาวน์โหลดจาก NPM | bool | false | เลขที่ |
| การปรับใช้ _name | ตัวระบุสำหรับกลุ่มการปรับใช้ (อนุญาตให้ใช้อักขระตัวอักษรและตัวเลขเพียงตัวพิมพ์เล็กและยัติภังค์เท่านั้น) | string | "tf-next" | เลขที่ |
| enable_multiple_deployments | ควบคุมว่าควรจะเป็นไปได้หรือไม่ที่จะเรียกใช้การปรับใช้หลาย ๆ แบบขนาน (ต้องใช้ multiple_deployments_base_domain) | bool | false | เลขที่ |
| image_optimization_lambda_memory_size | จำนวนหน่วยความจำใน MB ฟังก์ชั่น Lambda Worker สำหรับการเพิ่มประสิทธิภาพรูปภาพสามารถใช้ได้ ค่าที่ถูกต้องระหว่าง 128 MB ถึง 10,240 MB โดยเพิ่มขึ้น 1 MB | number | 2048 | เลขที่ |
| lambda_attach_policy_json | ไม่ว่าจะเป็นการปรับใช้นโยบาย Lambda JSON เพิ่มเติมหรือไม่ หากเป็นเท็จ lambda_policy_json จะไม่ถูกแนบกับฟังก์ชันแลมบ์ดา (จำเป็นเนื่องจากสตริงนโยบายเป็นที่รู้จักหลังจากใช้เมื่อใช้ terraforms data.aws_iam_policy_document) | bool | false | เลขที่ |
| lambda_attach_to_vpc | ตั้งค่าเป็นจริงหากควรแนบฟังก์ชั่นแลมบ์ดากับ VPC ใช้การตั้งค่านี้หากควรเข้าถึงทรัพยากร VPC โดยฟังก์ชั่นแลมบ์ดา เมื่อตั้งค่าเป็นจริงให้ใช้ VPC_SECURITION_GROUP_IDS และ VPC_SUBNET_IDS เพื่อระบุเครือข่าย VPC โปรดทราบว่าการแนบ VPC จะแนะนำความล่าช้าในการเริ่มต้นเย็น | bool | false | เลขที่ |
| lambda_policy_json | เอกสารนโยบายเพิ่มเติมเป็น JSON เพื่อแนบกับบทบาทฟังก์ชันแลมบ์ดา | string | null | เลขที่ |
| lambda_role_permissions_boundary | นโยบายของ IAM ที่กำหนดขอบเขตการเข้าถึง AWS_IAM_ROLE สำหรับแลมบ์ดา | string | null | เลขที่ |
| multiple_deployments_base_domain | โดเมนไวด์การ์ดเริ่มต้นที่ควรมีการปรับใช้ใหม่ ควรอยู่ในรูปแบบของ *.example.com | string | null | เลขที่ |
| แท็ก | Tag Metadata เพื่อติดฉลากทรัพยากร AWS ที่รองรับแท็ก | map(string) | {} | เลขที่ |
| tags_s3_bucket | Tag Metadata เพื่อติดฉลากถัง AWS S3 แทนที่แท็กที่มีชื่อเดียวกันในแท็กตัวแปรอินพุต | map(string) | {} | เลขที่ |
| vpc_security_group_ids | รายการ ID กลุ่มความปลอดภัยที่จะใช้โดยฟังก์ชั่นแลมบ์ดา Lambda_attach_to_vpc ควรตั้งค่าเป็นจริงสำหรับสิ่งเหล่านี้ที่จะนำไปใช้ | list(string) | [] | เลขที่ |
| vpc_subnet_ids | รายการของ VPC Subnet IDs เพื่อแนบฟังก์ชั่นแลมบ์ดา Lambda_attach_to_vpc ควรตั้งค่าเป็นจริงสำหรับสิ่งเหล่านี้ที่จะนำไปใช้ | list(string) | [] | เลขที่ |
| ชื่อ | คำอธิบาย |
|---|---|
| api_endpoint | จุดสิ้นสุด API ที่ CLI ใช้ |
| api_endpoint_access_policy_arn | อาร์นของนโยบายที่ให้การเข้าถึงจุดสิ้นสุด API |
| cloudfront_custom_error_response | การตอบสนองต่อข้อผิดพลาดที่กำหนดเองล่วงหน้าการแจกแจงแบบ CloudFront ควรใช้ |
| CloudFront_default_cache_behavior | พฤติกรรมแคชเริ่มต้นที่กำหนดไว้ล่วงหน้าการแจกแจงแบบ Cloudfront ควรใช้ |
| cloudfront_default_root_object | วัตถุรูทที่กำหนดค่าไว้ล่วงหน้าการแจกแจงแบบ Cloudfront ควรใช้ |
| CloudFront_domain_name | โดเมนของการแจกแจงเมฆเมฆหลัก (เมื่อสร้างขึ้น) |
| CloudFront_hosted_zone_id | โซน ID ของการแจกแจงเมนเมนต์ฟรอนต์ (เมื่อสร้างขึ้น) |
| cloudfront_ordered_cache_behaviors | พฤติกรรมแคชที่สั่งซื้อล่วงหน้าการแจกแจงแบบเมฆควรใช้ |
| CloudFront_origins | ต้นกำเนิดที่กำหนดค่าไว้ล่วงหน้าการกระจาย Cloudfront ควรใช้ |
| upload_bucket_id | N/A |
ภายใต้ฮูดโมดูลนี้ใช้ท่อส่งของ Vercel จำนวนมาก ดังนั้นปัญหาที่มีอยู่ใน Vercel มีแนวโน้มที่จะเกิดขึ้นในโครงการนี้เช่นกัน
การลบสแต็ค ( terraform destroy ) ล้มเหลวในการวิ่งครั้งแรก (Terraform-Provider-AWS#1721)
นี่เป็นความตั้งใจเพราะเราไม่สามารถลบฟังก์ชั่น Lambda@Edge (ใช้โดยโมดูลพร็อกซี) ในแบบซิงโครนัส อาจใช้เวลาถึงหนึ่งชั่วโมงสำหรับ AWS ในการปลดฟังก์ชัน Lambda@Edge จากการกระจาย Cloudfront แม้ว่าการกระจายถูกทำลายไปแล้ว
วิธีแก้ปัญหา:
หลังจากเรียกใช้คำสั่ง terraform destroy เริ่มต้น (ที่ล้มเหลว) รอ ~ 1 ชั่วโมงและเรียกใช้คำสั่งอีกครั้ง เวลานี้ควรทำงานให้สำเร็จและลบส่วนที่เหลือของสแต็ก
เริ่มต้นใช้งานล้มเหลวด้วยข้อผิดพลาดข้อความแสดง Error: error creating Lambda Event Source Mapping (#138)
มีเงื่อนไขการแข่งขันบางอย่างเมื่อมีการสร้างสิทธิ์สำหรับการปรับใช้แบบคงที่แลมบ์ดา สิ่งนี้ควรเกิดขึ้นในการปรับใช้ครั้งแรกเท่านั้น
วิธีแก้ปัญหา:
คุณควรจะสามารถ terraform apply ได้อีกครั้งและการสร้างสแต็กจะดำเนินต่อไปโดยไม่มีข้อผิดพลาดนี้
ยินดีต้อนรับ!
หากคุณต้องการปรับปรุงโมดูลนี้โปรดดูแนวทางการสนับสนุนของเราเพื่อเริ่มต้น
โครงการนี้ได้รับการดูแลโดยโครงสร้างพื้นฐานของ Millivolt
เราสร้างโซลูชันโครงสร้างพื้นฐานที่กำหนดเองสำหรับผู้ให้บริการคลาวด์
Apache -2.0 - ดูรายละเอียดใบอนุญาต
หมายเหตุ: โครงการตัวอย่างทั้งหมดใน
examples/*ได้รับอนุญาตเป็น MIT เพื่อให้สอดคล้องกับตัวอย่างอย่างเป็นทางการต่อไป