Tác giả: pmm (Zakiya Randall và Muru Bhaskaran)
Ngày phát hành: 14 THÁNG 3, 2025
Chuyên mục: Containers, Technical How-to
Bài viết này được viết bởi Zakiya Randall, Technical Account Manager và đồng tác giả Muru Bhaskaran, Sr. Specialist Solutions Architect.
Giới thiệu
Trong bối cảnh điện toán không ngừng phát triển, việc hỗ trợ đa dạng các kiến trúc máy tính ngày càng được chú trọng. Sự thay đổi này xuất phát từ nhu cầu về tính linh hoạt, hiệu quả và tối ưu hóa hiệu năng trên các nền tảng phần cứng khác nhau. Do đó, việc xây dựng các image container tương thích với nhiều kiến trúc (multi-arch) đã trở nên ngày càng quan trọng đối với các nhà phát triển và tổ chức.
AWS CodeBuild là một dịch vụ tích hợp liên tục được quản lý hoàn toàn, hiện đã hỗ trợ các runner GitHub Actions được quản lý. Đây là các runner tự host (self-hosted) cho phép người dùng cấu hình các project CodeBuild của họ để nhận các sự kiện job từ workflow GitHub Actions. Trong bài viết này, chúng tôi sẽ trình bày một giải pháp sử dụng GitHub, các workflow GitHub Actions và CodeBuild để xây dựng các image container gốc cho cả môi trường compute dựa trên x86 và AWS Graviton trên AWS. Sau khi hoàn thành workflow GitHub Actions, chúng ta sẽ tiến hành đẩy các image đa kiến trúc của mình lên Amazon Elastic Container Registry (Amazon ECR).
Tổng quan giải pháp
Sơ đồ kiến trúc dưới đây minh họa luồng công việc diễn ra khi một thay đổi được commit vào repository GitHub, chi tiết hóa các bước tiếp theo liên quan đến việc đẩy image container lên Amazon ECR.

Hình 1: Sơ đồ kiến trúc giải pháp
- Commit một thay đổi vào repository GitHub sẽ kích hoạt workflow.
- Các runner CodeBuild cho cả hai kiến trúc được khởi động để xây dựng các image container.
- Mã nguồn được checkout từ repository GitHub.
- Thông tin xác thực được cấu hình để truy cập vào tài khoản AWS.
- Một role được sử dụng để đăng nhập vào Amazon ECR.
- Image đa kiến trúc được xây dựng với danh sách các image cho cả hai kiến trúc.
Điều kiện tiên quyết
Để hoàn thành giải pháp này, bạn cần có các điều kiện tiên quyết sau:
- Tài khoản AWS
- Amazon Command Line Interface (AWS CLI)
- Một repository GitHub
Hướng dẫn chi tiết
Các bước sau đây sẽ hướng dẫn bạn thực hiện giải pháp này.
Tạo các tệp trong repository GitHub
Để bắt đầu xây dựng giải pháp, bạn cần một repository GitHub để lưu trữ Dockerfile, tệp index.html và tệp YAML của workflow GitHub Actions. Tham khảo Tạo một repository GitHub mới để biết hướng dẫn từng bước. Đối với ví dụ này, các tệp sau cần được commit vào thư mục gốc của repository GitHub.
- Tệp
index.html
<!DOCTYPE html>
<html>
<body>
<h1>Containers</h1>
<p>You can run containers!</p>
</body>
</html>
- Các chỉ thị
Dockerfileđể xây dựng image container
FROM public.ecr.aws/nginx/nginx
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
Tạo hai project CodeBuild cho kiến trúc compute x86 và arm64
Bạn phải tạo hai project CodeBuild để chạy các job GitHub Actions của mình. Các project CodeBuild của bạn nên tuân theo cấu trúc đặt tên sau: <tên-project>-x86 và <tên-project>-arm64. Tham khảo hướng dẫn sau để thiết lập hai project CodeBuild cho môi trường compute x86 và arm64. Bạn nên sử dụng phương thức xác thực ứng dụng OAuth để kết nối với repository GitHub của mình. Đối với các project CodeBuild x86 và arm64, hãy chọn một image môi trường được hỗ trợ phù hợp với từng kiến trúc compute. Các thông số kỹ thuật build Buildspec của bạn sẽ bị bỏ qua. Thay vào đó, CodeBuild sẽ ghi đè nó để sử dụng các lệnh thiết lập runner compute.

Hình 2: Các Project CodeBuild cho x86 và arm64
Tạo một repository Amazon ECR
Bạn cũng cần tạo một repository Amazon ECR để lưu trữ các image container x86 và arm64. Chạy lệnh AWS CLI sau để tạo một repository Amazon ECR.
aws ecr create-repository \
--repository-name <repository-name>
Sau khi tạo và định nghĩa repository Amazon ECR, bạn phải định nghĩa một role để các runner CodeBuild có quyền truy cập và đẩy các image của bạn lên repository Amazon ECR. Role bạn tạo sau đây cho phép bạn đẩy image lên repository Amazon ECR của mình.
- Truy cập IAM console và tạo một policy với các quyền sau. Trong phần Resource của câu lệnh
AllowPushPulltrong policy, hãy thay thế AWS Region, số tài khoản và tên repository của bạn bằng Amazon Resource Name (ARN) liên kết đến repository riêng tư của bạn trong Amazon ECR. Chỉ định một tên cho policy này và chọn Create Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPushPull",
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
],
"Resource": [
"arn:aws:ecr:us-east-1:xxxxxxxxxxxx:repository/<repository-name>"
]
},
{
"Sid": "AllowLogin",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": [
"*"
]
}
]
}
Sau khi tạo policy, hãy truy cập console AWS Identity and Access Management (IAM) để tạo một Identity Provider và chọn OpenID Connect. Đối với Provider URL, chọn https://token.actions.githubusercontent.com. Đối với Audience, chọn sts.amazonaws.com.
- Sau khi bạn tạo provider, hãy tạo một role và chọn Web Identity. Trong hộp thả xuống, bạn sẽ thấy Provider URL cho https://token.actions.githubusercontent.com. Chọn tùy chọn này và chỉ định http://sts.amazonaws.com cho Audience của bạn. Trong GitHub organization, chỉ định Tổ chức GitHub của bạn và thêm repository mà bạn đã tạo trong phần thiết lập ban đầu. Chọn Next.

Hình 3: Ví dụ về việc tạo role
- Trên trang Add Permissions, chọn policy mà bạn đã tạo ở Bước 1 để bạn có thể đẩy image lên Amazon ECR. Chọn Next. Trên màn hình tiếp theo, đặt tên cho role và chọn Create role.

Hình 4: Ví dụ về việc thêm quyền policy
- Truy cập Settings trong repository GitHub của bạn, và dưới mục Security ở khung bên trái, chọn Secrets and Variables. Chọn tab Actions trong Secrets and Variables. Chọn New repository secret. Đối với tên, nhập
AWS_ROLE_ARN, nhập ARN của Role AWS mà bạn đã tạo ở Bước 3, và chọn Add secret.

Hình 5: Ví dụ về việc tạo secret GitHub Actions cho Role AWS
- Tạo một New repository secret khác cho AWS_REGION. Chỉ định Region mà bạn đã tạo tài nguyên và chọn Add secret.

Hình 6: Ví dụ về secret GitHub Actions cho AWS Region
Chuẩn bị workflow GitHub Actions
Một workflow GitHub Actions là một quy trình tự động có thể cấu hình, bao gồm một hoặc nhiều job và bạn có thể định nghĩa các job này trong một tệp YAML. Bạn sẽ tạo một tệp YAML trong thư mục .github/workflows trong repository GitHub của mình để định nghĩa workflow cho giải pháp. Tệp YAML cho workflow GitHub Actions của bạn chứa các job build được chỉ định cho các runner CodeBuild của bạn. Môi trường runner được chỉ định trong phần runs-on của tệp YAML, tham chiếu đến từng project CodeBuild mà bạn tạo cho giải pháp đa kiến trúc của mình.
- container-image.yaml
name: Docker
on:
workflow_dispatch: {}
push:
branches: [ "main" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
env:
REGISTRY: xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com
IMAGE_NAME: myapp
jobs:
build:
strategy:
matrix:
arch: [arm64, x86]
runs-on: codebuild-myapp-${{ matrix.arch }}-${{ github.run_id }}-${{ github.run_attempt }}
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR Private
if: github.event_name != 'pull_request'
id: login-to-ecr
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
with:
registry-type: private
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build (and optionally) push Docker image (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}-${{ matrix.arch }}
labels: ${{ steps.meta.outputs.labels }}
manifest:
needs: build
runs-on: codebuild-myapp-x86-${{ github.run_id }}-${{ github.run_attempt }}
permissions:
contents: read
id-token: write
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR Private
if: github.event_name != 'pull_request'
id: login-ecr
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
with:
registry-type: private
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push image manifest (don't push on PR)
# https://github.com/Noelware/docker-manifest-action
- name: Build and push Docker manifest
id: build-and-push
uses: Noelware/docker-manifest-action@master # v0.3.0
with:
images: ${{ steps.meta.outputs.tags }}-arm64,${{ steps.meta.outputs.tags }}-x86
inputs: ${{ steps.meta.outputs.tags }}
push: ${{ github.event_name != 'pull_request' }}
Trong phần env variables trong tệp cấu hình workflow GitHub Actions của bạn, bạn phải định nghĩa repository Amazon ECR mà bạn đã tạo để các job GitHub Actions của bạn biết nơi để đẩy manifest và image container. Repository bạn đã tạo được đặt trong biến env cho IMAGE_NAME.
env:
REGISTRY: xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com
IMAGE_NAME: <repository-name>
Trong tệp YAML workflow GitHub Actions của bạn, bạn phải định nghĩa cả hai project CodeBuild trong giá trị runs-on để xác định kiến trúc compute mà các runner được host của bạn đang sử dụng để thực thi các job. Ở đây chúng tôi đã định nghĩa các biến arm64 và x86 trong trường matrix. Một job sẽ chạy cho mỗi sự kết hợp của các biến được định nghĩa trong trường arch trong matrix. Bạn phải chỉ định tên project CodeBuild làm tiền tố để job của bạn được runner CodeBuild nhận diện.
Giá trị runs-on trong tệp cấu hình của bạn nên như sau:
runs-on: codebuild-<project-name>-${{ matrix.arch }}-${{ github.run_id }}-${{ github.run_attempt }}
jobs:
build:
strategy:
matrix:
arch: [arm64, x86]
runs-on: codebuild-myapp-${{ matrix.arch }}-${{ github.run_id }}-${{ github.run_attempt }}
Trong tệp cấu hình workflow GitHub Actions của bạn, các biến secret của GitHub được định nghĩa cho AWS_ROLE_ARN và AWS_REGION. GitHub sẽ lấy các biến secret này khi chúng ta cần cấu hình thông tin xác thực để truy cập AWS.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ secrets.AWS_REGION }}
Sau khi tất cả các tệp được tải lên repository GitHub của bạn, repository của bạn sẽ trông tương tự như hình ảnh sau. Dockerfile và tệp index.html được đặt trong thư mục gốc của repository, và tệp container-image.yaml được đặt trong thư mục .github/workflows để định nghĩa workflow GitHub Actions của bạn.

Hình 7: Ví dụ về cấu trúc tệp trong repository GitHub
Bên trong thư mục .github/workflows là nơi lưu trữ tệp container-image.yaml của bạn.

Hình 8: Ví dụ về tệp YAML của workflow GitHub Actions
Kiểm thử giải pháp
Bây giờ tất cả các tài nguyên của bạn đã được tạo trong GitHub và AWS, đã đến lúc kiểm thử giải pháp. Thay đổi thông điệp trong tệp index.html trong repository GitHub của bạn và commit các thay đổi vào nhánh main để workflow GitHub Actions của bạn có thể được kích hoạt. Khi workflow GitHub Actions của bạn được kích hoạt, các runner CodeBuild của bạn sẽ bắt đầu thực thi các job mà chúng ta đã chỉ định trong tệp cấu hình.
- Trong tệp index.html của bạn, thay đổi thông điệp trong phần body của văn bản. Commit các thay đổi của bạn và đẩy lên nhánh main.
- Quay lại trang chủ của repository GitHub của bạn và chọn Actions ở thanh trên cùng. Khi bạn chọn Actions, bạn sẽ thấy một trang mô tả các job đang chạy cho quá trình build cho cả hai kiến trúc compute như trong hình sau.

Hình 9: Các job build bắt đầu cho cả hai kiến trúc compute
- Trong mỗi job build, bạn sẽ thấy các bước mà quá trình build đang hoàn thành cho cả hai kiến trúc compute. Nó thông báo rằng đang chờ một runner nhận job này.

Hình 10: runner compute x86

Hình 11: runner compute arm64
- Truy cập CodeBuild trong AWS Console, bạn sẽ thấy cả hai project build của chúng ta cho các kiến trúc compute hiện đang ở trạng thái In-Progress. Có thể mất vài phút để quá trình build hoàn tất.

Hình 12: Các project CodeBuild cho cả hai kiến trúc
- Nếu bạn quay lại trang Actions trong repository GitHub của mình, bạn có thể thấy rằng cả hai job build đã hoàn thành cho các kiến trúc compute x86 và arm64. Job manifest đang tạo một danh sách manifest chứa các image container x86 và arm64 của bạn.

Hình 13: Các bản build đã hoàn thành trên trang GitHub Actions
- Nếu bạn vào repository Amazon ECR của mình, bạn sẽ thấy rằng các image đã được cập nhật cho các image container x86 và arm64 cho manifest của bạn.

Hình 14: Build image hoàn tất trong ECR
Dọn dẹp tài nguyên
Để tránh phát sinh thêm chi phí, hãy đảm bảo bạn hủy tất cả cơ sở hạ tầng đã cấp phát liên quan đến các ví dụ được trình bày chi tiết trong bài viết này. Để dọn dẹp các tài nguyên GitHub, bạn có thể xóa repository đã được sử dụng cho giải pháp này. Để dọn dẹp các tài nguyên AWS, bạn có thể xóa hai project CodeBuild bằng các lệnh sau.
aws codebuild delete-project –-name <project-name>-x86
aws codebuild delete-project –-name <project-name>-arm64
Bạn có thể xóa repository Amazon ECR của mình bằng lệnh sau.
aws ecr delete-repository \
--repository-name <repository-name> \
--force
Kết luận
Trong bài viết này, chúng tôi đã trình bày cách tích hợp GitHub Actions với AWS CodeBuild để xây dựng các image đa kiến trúc. Chúng tôi cũng đã hướng dẫn quy trình lưu trữ các image đa kiến trúc này trong Amazon ECR để chúng có thể được truy xuất bởi môi trường compute x86 hoặc Amazon Elastic Compute Cloud (Amazon EC2)-AWS Graviton. CodeBuild cung cấp một trang web chuyên dụng cung cấp thêm thông tin, hướng dẫn và tài nguyên được thiết kế để hỗ trợ người dùng bắt đầu triển khai các runner để nâng cao pipeline của họ. Nếu bạn muốn biết thêm về môi trường compute Graviton, hãy tham khảo trang web của chúng tôi.