A multi-architecture container image build system using GitHub Actions and Alibaba Cloud Spot instances for cost-effective, high-performance automated builds.
This project provides an automated build pipeline for multi-architecture (AMD64/ARM64) container images using:
- GitHub Actions for CI/CD orchestration
- Alibaba Cloud Spot Instances for ultra-low-cost native architecture builds
- Self-hosted Runners for build execution
- Custom image management for optimized runner base images
The root Dockerfile is a customized OpenResty image based on the upstream OpenResty Dockerfile.
- Native AMD64 and ARM64 builds (no QEMU emulation overhead)
- Automatic architecture-specific image tagging
- Multi-arch manifest merging for unified tags
- Ultra-low cost: ~¥0.05-0.1 per build using Spot instances
- Automatic cleanup: Instances self-destruct after build completion
- Dynamic instance selection: Automatically selects optimal instance types based on pricing
- Automated custom image building for runner base images
- Image family support (
ALIYUN_IMAGE_FAMILY) for automatic latest image retrieval - Intelligent image cleanup: keeps
-latestsuffix for new images, renames old images with date suffix - Configurable image retention (default: 5 images per prefix)
- Dynamic VSwitch selection based on availability zone
- Disk category fallback strategy (cloud_essd → cloud_ssd → cloud_efficiency)
- Instance tagging for resource tracking
- Self-destruct mechanism with fallback cleanup
Builds AMD64 architecture images on native AMD64 Spot instances.
Features:
- Dynamic spot instance selection
- Self-hosted runner auto-configuration
- Automatic instance cleanup
- Architecture-specific tagging (
<tag>-amd64)
Builds ARM64 architecture images on native ARM64 Spot instances.
Features:
- Same as AMD64 workflow but for ARM64 architecture
- Architecture-specific tagging (
<tag>-arm64)
Builds and manages custom Ubuntu 24 base images for self-hosted runners.
Features:
- Automated custom image creation from spot instances
- Image family support for automatic base image selection
- Dynamic system disk sizing based on image size
- Image cleanup with date-suffix renaming
- Support for both AMD64 and ARM64 architectures
Trigger:
- Scheduled: Daily at 02:00 UTC (10:00 Beijing time)
- Manual: Workflow dispatch with optional force build
Merges AMD64 and ARM64 images into unified multi-architecture manifests.
Features:
- Creates unified tags (e.g.,
latest,v1.0.0) - Docker automatically selects correct architecture at runtime
- On-demand merging (manual trigger)
-
Trigger Build
- Manual workflow dispatch (primary method)
- Auto-triggers (push/tags) currently disabled - see Iteration 7 in iteration plan
-
Instance Creation
- Dynamic spot instance selection using
spot-instance-advisor - Optimal instance type selection based on pricing
- Automatic VSwitch selection by availability zone
- Self-hosted runner configuration (Ephemeral mode)
- Dynamic spot instance selection using
-
Build Execution
- Native architecture build (no emulation)
- Push to GitHub Container Registry
- Architecture-specific tagging:
<tag>-amd64or<tag>-arm64
-
Cleanup
- Instance self-destruct script (primary mechanism)
- Workflow cleanup job (fallback verification)
- Zero cost accumulation
-
Trigger Merge
- Manual workflow dispatch after both AMD64 and ARM64 builds complete
- Input target tag (without architecture suffix, e.g.,
latestorv1.0.0) - Auto-trigger on build completion currently disabled - see Iteration 9 in iteration plan
-
Merge Execution
- Verify architecture-specific images exist (
<tag>-amd64and<tag>-arm64) - Create and push multi-arch manifest (
<tag>) - Docker automatically selects correct architecture at runtime
- Verify architecture-specific images exist (
The custom image building workflow creates optimized Ubuntu 24 base images for self-hosted runners with pre-installed tools.
- Image Family Support: Uses
ALIYUN_IMAGE_FAMILYenvironment variable to automatically retrieve the latest base image - Dynamic Size Calculation: Automatically queries image size (in GB) and sets system disk size accordingly
- Intelligent Cleanup:
- New images always keep
-latestsuffix - Old images renamed with date suffix (e.g.,
github-runner-ubuntu24-amd64-202511201200) - Total images (latest + dated) counted and kept within
KEEP_IMAGE_COUNTlimit
- New images always keep
- Version Tracking: Uses version hash to detect existing images and skip rebuilds
- Latest image:
<prefix>-<arch>-latest(e.g.,github-runner-ubuntu24-amd64-latest) - Historical images:
<prefix>-<arch>-YYYYMMDDHHMM(e.g.,github-runner-ubuntu24-amd64-202511201200)
Key environment variables:
ALIYUN_IMAGE_FAMILY: Image family name for automatic base image selectionIMAGE_NAME_PREFIX: Prefix for custom image names (default:github-runner-ubuntu24)KEEP_IMAGE_COUNT: Number of images to retain (default: 5)
Images are pushed to GitHub Container Registry:
- Multi-arch merged images (recommended):
ghcr.io/dianplus/openresty:<tag>- Docker automatically matches platform - Architecture-specific images (for debugging):
ghcr.io/dianplus/openresty:<tag>-amd64orghcr.io/dianplus/openresty:<tag>-arm64
Option 1: Automatic Trigger (Recommended)
- Push changes to
developormasterbranch to automatically trigger both AMD64 and ARM64 builds - Create a tag with
v*pattern (e.g.,v1.0.0) to automatically trigger both AMD64 and ARM64 builds
Option 2: Manual Trigger
- Manually trigger
Build AMD64workflow - Manually trigger
Build ARM64workflow - Wait for both builds to complete
Option 1: Automatic Trigger (Recommended)
- After both AMD64 and ARM64 builds complete successfully, the
Merge Multi-Arch Manifestsworkflow will automatically run - The merged manifest will be tagged and pushed automatically based on the source branch or tag
Option 2: Manual Trigger
- Navigate to GitHub Actions page
- Find
Merge Multi-Arch Manifestsworkflow - Click "Run workflow"
- Enter target tag (e.g.,
latestorv1.0.0) - Click "Run workflow" to execute merge
# Pull multi-arch image (recommended, Docker auto-matches platform)
docker pull ghcr.io/dianplus/openresty:latest
# Pull architecture-specific image (for debugging)
docker pull ghcr.io/dianplus/openresty:latest-amd64
docker pull ghcr.io/dianplus/openresty:latest-arm64# Get image ID by name
export ALIYUN_REGION_ID=cn-hangzhou
export IMAGE_NAME=github-runner-ubuntu24-amd64-latest
python3 .github/scripts/get-image-id-by-name.pybuild-custom-image.py: Custom image building with comprehensive image managementselect-instance.py: Optimal spot instance type selectioncreate-spot-instance.py: Spot instance creation with retry mechanism
generate-user-data.sh: User data generation for runner configurationget-registration-token.sh: Runner registration token retrievalwait-for-runner.sh: Runner online status monitoring
self-destruct.sh: Automatic instance terminationcleanup-instance.sh: Fallback cleanup mechanismdebug-self-destruct.sh: Troubleshooting tool
query-ubuntu-image.py: Ubuntu image queryingget-image-id-by-name.py: Image ID lookup by namepublish-image-to-marketplace.py: Marketplace publishing
ALIYUN_REGION_ID: Alibaba Cloud region IDALIYUN_VPC_ID: VPC IDALIYUN_SECURITY_GROUP_ID: Security group IDALIYUN_VSWITCH_ID_*: VSwitch IDs for each availability zone (A-Z)ALIYUN_AMD64_IMAGE_FAMILY: Image family for AMD64 base imagesALIYUN_ARM64_IMAGE_FAMILY: Image family for ARM64 base imagesALIYUN_KEY_PAIR_NAME: SSH key pair nameALIYUN_ECS_SELF_DESTRUCT_ROLE_NAME: RAM role for instance self-destruct
IMAGE_NAME_PREFIX: Custom image name prefix (default:github-runner-ubuntu24)KEEP_IMAGE_COUNT: Number of images to retain (default: 5)IMAGE_BUILD_MIN_CPU: Minimum CPU cores for image build instances (default: 2)IMAGE_BUILD_MAX_CPU: Maximum CPU cores for image build instances (default: 8)
ALIYUN_ACCESS_KEY_ID: Alibaba Cloud access key IDALIYUN_ACCESS_KEY_SECRET: Alibaba Cloud access key secretGITHUB_TOKEN: GitHub token for runner registration (withreposcope)
- Native Builds: AMD64 and ARM64 images built on native architecture instances, no QEMU emulation overhead
- Ultra-Low Cost: ~¥0.05-0.1 per build using Spot instances
- Automatic Cleanup: Instances self-destruct after build completion
- Flexible Merging: On-demand multi-arch manifest merging
- Intelligent Image Management: Automatic cleanup and version tracking
- Dynamic Resource Selection: Optimal instance and disk type selection
For detailed configuration and requirements, see:
- Project Overview
- Workflow Details
- Alibaba Cloud Configuration
- Runner Setup
- Network Configuration
- Troubleshooting
- Dynamic Instance Selection
2-clause BSD License (see LICENSE file)