CodeBuild: Project, buildspec.yml và Lần Build Đầu Tiên
Code đã nằm trên CodeCommit. Chặng tiếp theo của dây chuyền là build: lấy source đó, chạy các bước biên dịch/test/đóng gói, cho ra một artifact sẵn sàng để deploy. Đây là việc của CodeBuild. Bài này tạo một build project, viết file buildspec.yml định nghĩa các bước, chạy build thật trên app đã push ở bài trước, rồi đọc log để thấy chính xác CodeBuild làm gì.
Mục tiêu
Hiểu CodeBuild chạy một build ra sao (không chỉ "bấm build"), viết được buildspec.yml, tạo project bằng CLI và đọc kết quả qua phase và log.
buildspec.yml: công thức build
CodeBuild không đoán cách build app của bạn — bạn khai trong một file buildspec.yml đặt ở gốc repo. Tài liệu mô tả nó là "tập các lệnh build và thiết lập, dạng YAML, mà CodeBuild dùng để chạy build". Cấu trúc xoay quanh các phase chạy tuần tự:
version: 0.2
phases:
install:
commands:
- echo "Install phase — preparing the build environment"
pre_build:
commands:
- echo "Pre-build — validating the source"
- test -f index.html && echo "index.html present"
build:
commands:
- echo "Build phase — static site, packaging as-is"
- echo "<!-- built by CodeBuild at $(date -u) -->" >> index.html
post_build:
commands:
- echo "Post-build — build finished"
artifacts:
files:
- index.html
- appspec.yml
- 'scripts/**/*'
name: awscicd-demo-app
Bốn phase bạn khai: install (cài công cụ/runtime), pre_build (chuẩn bị, đăng nhập registry, kiểm tra), build (lệnh build chính), post_build (đóng gói, đẩy image...). App của ta là trang tĩnh nên các lệnh chỉ minh hoạ; với app thật đây là nơi gọi npm run build, mvn package, go build... Khối artifacts khai những file nào sẽ được gói lại thành output — ở đây gồm index.html cùng appspec.yml và scripts/ mà bài deploy sẽ thêm. Commit file này vào repo và push lên CodeCommit (git push origin main).
Chọn môi trường build
CodeBuild chạy build trong một container Docker dựng sẵn. AWS cung cấp sẵn các image "curated"; đừng nhớ tên theo trí nhớ vì danh sách thay đổi — hỏi thẳng API:
$ aws codebuild list-curated-environment-images \
--query "platforms[].languages[].images[].name" --output text \
| tr '\t' '\n' | grep amazonlinux-x86_64-standard
aws/codebuild/amazonlinux-x86_64-standard:6.0
...
Bản chuẩn mới nhất lúc viết là aws/codebuild/amazonlinux-x86_64-standard:6.0 (dựa trên Amazon Linux 2023). Đây là image ta dùng. Mẹo: trong cấu hình bạn có thể chọn "luôn dùng bản mới nhất của runtime" để hưởng cache AMI và rút ngắn thời gian provisioning.
Tạo build project
Project gắn ba thứ lại: source (lấy code ở đâu), environment (build trong image nào), artifacts (đẩy output đi đâu), cộng service role (bài 2) để có quyền. Khai bằng một file JSON cho gọn:
{
"name": "awscicd-demo-build",
"source": {
"type": "CODECOMMIT",
"location": "https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/awscicd-demo-app",
"buildspec": "buildspec.yml"
},
"sourceVersion": "refs/heads/main",
"artifacts": {
"type": "S3",
"location": "awscicd-artifacts-111122223333-ap-southeast-1",
"path": "builds", "packaging": "ZIP", "name": "awscicd-demo-app.zip"
},
"environment": {
"type": "LINUX_CONTAINER",
"image": "aws/codebuild/amazonlinux-x86_64-standard:6.0",
"computeType": "BUILD_GENERAL1_SMALL"
},
"serviceRole": "arn:aws:iam::111122223333:role/awscicd-codebuild-role"
}
$ aws codebuild create-project --cli-input-json file://cb-project.json \
--query 'project.[name,environment.image,serviceRole]' --output text
awscicd-demo-build aws/codebuild/amazonlinux-x86_64-standard:6.0 arn:aws:iam::111122223333:role/awscicd-codebuild-role
Project trỏ source vào CodeCommit, artifact vào bucket S3 từ bài 2, và chạy dưới service role CodeBuild đã tạo — nhờ role đó nó có quyền codecommit:GitPull, ghi log, và ghi S3.
Chạy build thật
$ BUILD_ID=$(aws codebuild start-build --project-name awscicd-demo-build --query 'build.id' --output text)
$ echo "$BUILD_ID"
awscicd-demo-build:67099cde-784b-4788-a31c-dd8004c5cae8
Build chạy bất đồng bộ; poll trạng thái tới khi xong:
$ aws codebuild batch-get-builds --ids "$BUILD_ID" \
--query 'builds[0].[buildStatus,currentPhase]' --output text
IN_PROGRESS PROVISIONING
...
SUCCEEDED COMPLETED
Build thực sự gồm những gì
Đây là phần đáng mổ. Một build không chỉ là "chạy lệnh của bạn" — CodeBuild đi qua một chuỗi phase, trong đó phase bạn khai (install/pre_build/build/post_build) chỉ là phần giữa. Xem toàn bộ:
$ aws codebuild batch-get-builds --ids "$BUILD_ID" \
--query 'builds[0].phases[].[phaseType,phaseStatus,durationInSeconds]' --output text
SUBMITTED SUCCEEDED 0
QUEUED SUCCEEDED 0
PROVISIONING SUCCEEDED 4
DOWNLOAD_SOURCE SUCCEEDED 5
INSTALL SUCCEEDED 0
PRE_BUILD SUCCEEDED 0
BUILD SUCCEEDED 0
POST_BUILD SUCCEEDED 0
UPLOAD_ARTIFACTS SUCCEEDED 0
FINALIZING SUCCEEDED 0
COMPLETED
PROVISIONING (4s) là lúc CodeBuild dựng container từ image; DOWNLOAD_SOURCE (5s) kéo code từ CodeCommit; rồi tới bốn phase từ buildspec.yml; UPLOAD_ARTIFACTS gói output đẩy lên S3; FINALIZING dọn dẹp. Container này phù du — dựng cho build này, chạy xong là vứt. Lần build sau dựng container mới, sạch hoàn toàn, nên build có tính tái lập: không có rác tồn từ lần trước.
CodeCommit (refs/heads/main)
│ DOWNLOAD_SOURCE
▼
┌─────── container tạm (amazonlinux-x86_64-standard:6.0) ───────┐
│ chạy buildspec.yml: │
│ INSTALL → PRE_BUILD → BUILD → POST_BUILD │
└───────┬───────────────────────────────────┬──────────────────┘
│ UPLOAD_ARTIFACTS │ mỗi dòng lệnh → log
▼ ▼
S3: builds/awscicd-demo-app.zip CloudWatch Logs
/aws/codebuild/awscicd-demo-build
Đọc log
Mỗi lệnh trong buildspec và đầu ra của nó được ghi lên CloudWatch Logs, nhóm /aws/codebuild/<project>. Xem vài dòng:
$ aws logs get-log-events --log-group-name /aws/codebuild/awscicd-demo-build \
--log-stream-name 67099cde-... --query 'events[].message' --output text
...
Running command test -f index.html && echo "index.html present"
index.html present
Phase complete: PRE_BUILD State: SUCCEEDED
Entering phase BUILD
Running command echo "Build phase — static site, packaging as-is"
Build phase — static site, packaging as-is
...
Phase complete: POST_BUILD State: SUCCEEDED
Log cho thấy từng lệnh chạy, output của nó, và ranh giới mỗi phase. Khi build fail, đây là chỗ đầu tiên cần nhìn — phase nào fail, lệnh nào, lỗi gì.
Artifact đã nằm trên S3, đóng gói ZIP:
$ aws s3 ls s3://awscicd-artifacts-111122223333-ap-southeast-1/builds/ --recursive
2026-05-25 12:53:07 342 builds/awscicd-demo-app.zip
🧹 Dọn dẹp
Project này được pipeline ở Part V dùng lại, nên giữ tới cuối series. Khi muốn xóa:
$ aws codebuild delete-project --name awscicd-demo-build
CodeBuild chỉ tính tiền theo phút build thực tế, không có gì chạy nền, nên giữ project không build thì không tốn phí.
Tổng kết
CodeBuild build theo công thức trong buildspec.yml: các phase install/pre_build/build/post_build chạy tuần tự trong một container tạm dựng từ image curated (mới nhất amazonlinux-x86_64-standard:6.0). Một project gắn source (CodeCommit), environment (image + compute) và artifacts (S3) lại, chạy dưới service role. Build đi qua chuỗi phase rộng hơn phần bạn khai (PROVISIONING, DOWNLOAD_SOURCE, UPLOAD_ARTIFACTS...); mỗi lệnh ghi log lên CloudWatch; artifact ra ZIP trên S3. Container phù du nên build tái lập được.
Bài tới đào sâu CodeBuild: truyền biến môi trường và secret an toàn (từ SSM Parameter Store / Secrets Manager), bật cache để build nhanh hơn, và tinh chỉnh khối artifacts.