#!/bin/bash set -e # Configuration REGISTRY="${REGISTRY:-gitea.ahkhan.me}" REGISTRY_PATH="${REGISTRY_PATH:-docker}" REPO_PREFIX="${REPO_PREFIX:-ubuntu}" PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" DATE_TAG=$(date +%Y-%m-%d) # Ubuntu versions to build (in order, latest first) UBUNTU_VERSIONS=("24.04" "22.04" "20.04") LATEST_VERSION="24.04" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color log() { echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1" } success() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1" } warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')]${NC} $1" } error() { echo -e "${RED}[$(date '+%H:%M:%S')]${NC} $1" } # Function to build single Ubuntu version build_ubuntu_version() { local version=$1 local repo_name="${REPO_PREFIX}-${version}" log "Building Ubuntu ${version}..." # Build tags for this version local tags=( "${REGISTRY}/${REGISTRY_PATH}/${repo_name}:latest" "${REGISTRY}/${REGISTRY_PATH}/${repo_name}:${DATE_TAG}" ) # Add ubuntu:latest tag only for the latest version if [[ "$version" == "$LATEST_VERSION" ]]; then tags+=("${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest") fi # Build tag arguments local tag_args="" for tag in "${tags[@]}"; do tag_args="$tag_args --tag $tag" done # Cache configuration local cache_from="${REGISTRY}/${REGISTRY_PATH}/${repo_name}:buildcache" local cache_to="${REGISTRY}/${REGISTRY_PATH}/${repo_name}:buildcache" log "Tags: ${tags[*]}" log "Cache from/to: $cache_from" # Build command docker buildx build \ --platform "$PLATFORMS" \ --build-arg UBUNTU_VER="$version" \ $tag_args \ --cache-from "type=registry,ref=$cache_from" \ --cache-to "type=registry,ref=$cache_to,mode=max" \ --push \ . success "Ubuntu ${version} build completed successfully" # Clear local builder cache to save disk space (registry cache is preserved) log "Clearing local builder cache for Ubuntu ${version}..." docker buildx prune --filter type=exec.cachemount --filter type=regular --force >/dev/null 2>&1 || true } # Function to validate Docker buildx setup validate_setup() { log "Validating Docker buildx setup..." if ! command -v docker &> /dev/null; then error "Docker is not installed or not in PATH" exit 1 fi if ! docker buildx version &> /dev/null; then error "Docker buildx is not available" exit 1 fi # Always use multiarch builder for consistency and reliability # Reasons: better registry caching, isolated BuildKit, predictable multi-arch behavior log "Setting up multiarch builder for optimal registry caching and multi-platform support..." # Install binfmt for cross-platform emulation log "Setting up cross-platform emulation..." docker run --privileged --rm tonistiigi/binfmt --install all # Create or reuse multiarch builder if docker buildx ls | grep -q "^multiarch"; then log "Using existing multiarch builder" docker buildx use multiarch else log "Creating new multiarch builder" docker buildx create --name multiarch --driver docker-container --use fi # Bootstrap the builder docker buildx inspect --bootstrap success "Multiarch builder setup completed" } # Function to show build summary show_summary() { log "Build Summary:" echo "Registry: $REGISTRY" echo "Date tag: $DATE_TAG" echo "Platforms: $PLATFORMS" echo "Ubuntu versions: ${UBUNTU_VERSIONS[*]}" echo "" echo "Images that will be built:" for version in "${UBUNTU_VERSIONS[@]}"; do echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:latest" echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:${DATE_TAG}" echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:buildcache (cache)" if [[ "$version" == "$LATEST_VERSION" ]]; then echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest" fi echo "" done } # Main execution main() { log "Starting Ubuntu Docker images build process" # Validate environment validate_setup # Show what will be built show_summary # Confirm before proceeding read -p "Proceed with build? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then warn "Build cancelled by user" exit 0 fi # Build each version for version in "${UBUNTU_VERSIONS[@]}"; do build_ubuntu_version "$version" done success "All Ubuntu images built successfully!" log "Available images:" for version in "${UBUNTU_VERSIONS[@]}"; do echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:latest" echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:${DATE_TAG}" done echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest (→ Ubuntu ${LATEST_VERSION})" } # Help function show_help() { echo "Ubuntu Docker Build Script" echo "" echo "Usage: $0 [OPTIONS]" echo "" echo "Environment Variables:" echo " REGISTRY Docker registry (default: gitea.ahkhan.me)" echo " REGISTRY_PATH Registry path (default: docker)" echo " REPO_PREFIX Repository prefix (default: ubuntu)" echo " PLATFORMS Target platforms (default: linux/amd64,linux/arm64)" echo "" echo "Examples:" echo " REGISTRY=myregistry.com ./build.sh" echo " PLATFORMS=linux/amd64 ./build.sh" echo "" } # Handle arguments case "${1:-}" in -h|--help) show_help exit 0 ;; *) main "$@" ;; esac