container-build.sh
1 #!/bin/bash 2 set -euo pipefail 3 4 # FerrisProof Container Build Script 5 # Optimized for Podman but works with Docker too 6 7 # Colors for output 8 RED='\033[0;31m' 9 GREEN='\033[0;32m' 10 YELLOW='\033[1;33m' 11 BLUE='\033[0;34m' 12 NC='\033[0m' # No Color 13 14 # Configuration 15 CONTAINER_ENGINE=${CONTAINER_ENGINE:-"podman"} 16 IMAGE_NAME=${IMAGE_NAME:-"ferris-proof"} 17 IMAGE_TAG=${IMAGE_TAG:-"latest"} 18 DOCKERFILE=${DOCKERFILE:-"Containerfile.alpine"} 19 REGISTRY=${REGISTRY:-""} 20 PLATFORM=${PLATFORM:-"linux/amd64"} 21 22 log_info() { 23 echo -e "${BLUE}[INFO]${NC} $1" 24 } 25 26 log_success() { 27 echo -e "${GREEN}[SUCCESS]${NC} $1" 28 } 29 30 log_warning() { 31 echo -e "${YELLOW}[WARNING]${NC} $1" 32 } 33 34 log_error() { 35 echo -e "${RED}[ERROR]${NC} $1" 36 } 37 38 check_container_engine() { 39 if ! command -v "$CONTAINER_ENGINE" &> /dev/null; then 40 log_error "$CONTAINER_ENGINE not found" 41 if [ "$CONTAINER_ENGINE" = "podman" ]; then 42 log_info "Install Podman: https://podman.io/getting-started/installation" 43 log_info "Falling back to Docker..." 44 if command -v docker &> /dev/null; then 45 CONTAINER_ENGINE="docker" 46 log_info "Using Docker instead" 47 else 48 log_error "Neither Podman nor Docker found" 49 exit 1 50 fi 51 else 52 exit 1 53 fi 54 fi 55 56 log_info "Using container engine: $CONTAINER_ENGINE" 57 } 58 59 build_image() { 60 local full_image_name="$IMAGE_NAME:$IMAGE_TAG" 61 if [ -n "$REGISTRY" ]; then 62 full_image_name="$REGISTRY/$full_image_name" 63 fi 64 65 log_info "Building image: $full_image_name" 66 log_info "Using Containerfile: $DOCKERFILE" 67 log_info "Platform: $PLATFORM" 68 69 local build_args=() 70 71 # Podman-specific optimizations 72 if [ "$CONTAINER_ENGINE" = "podman" ]; then 73 build_args+=( 74 "--layers" 75 "--platform=$PLATFORM" 76 ) 77 fi 78 79 # Docker-specific optimizations 80 if [ "$CONTAINER_ENGINE" = "docker" ]; then 81 build_args+=( 82 "--platform=$PLATFORM" 83 ) 84 fi 85 86 # Build the image 87 if $CONTAINER_ENGINE build \ 88 "${build_args[@]}" \ 89 -f "$DOCKERFILE" \ 90 -t "$full_image_name" \ 91 .; then 92 log_success "Image built successfully: $full_image_name" 93 else 94 log_error "Failed to build image" 95 exit 1 96 fi 97 98 # Show image size 99 local image_size 100 if [ "$CONTAINER_ENGINE" = "podman" ]; then 101 image_size=$($CONTAINER_ENGINE images --format "{{.Size}}" "$full_image_name") 102 else 103 image_size=$($CONTAINER_ENGINE images --format "table {{.Size}}" "$full_image_name" | tail -n1) 104 fi 105 log_info "Image size: $image_size" 106 107 return 0 108 } 109 110 test_image() { 111 local full_image_name="$IMAGE_NAME:$IMAGE_TAG" 112 if [ -n "$REGISTRY" ]; then 113 full_image_name="$REGISTRY/$full_image_name" 114 fi 115 116 log_info "Testing image: $full_image_name" 117 118 # Test basic functionality 119 if $CONTAINER_ENGINE run --rm "$full_image_name" --version; then 120 log_success "Image test passed" 121 else 122 log_error "Image test failed" 123 exit 1 124 fi 125 126 # Test help command 127 if $CONTAINER_ENGINE run --rm "$full_image_name" --help > /dev/null; then 128 log_success "Help command test passed" 129 else 130 log_error "Help command test failed" 131 exit 1 132 fi 133 } 134 135 push_image() { 136 if [ -z "$REGISTRY" ]; then 137 log_warning "No registry specified, skipping push" 138 return 0 139 fi 140 141 local full_image_name="$REGISTRY/$IMAGE_NAME:$IMAGE_TAG" 142 143 log_info "Pushing image: $full_image_name" 144 145 if $CONTAINER_ENGINE push "$full_image_name"; then 146 log_success "Image pushed successfully" 147 else 148 log_error "Failed to push image" 149 exit 1 150 fi 151 } 152 153 show_usage() { 154 echo "FerrisProof Container Build Script" 155 echo 156 echo "Usage: $0 [OPTIONS] [COMMAND]" 157 echo 158 echo "Commands:" 159 echo " build Build the container image (default)" 160 echo " test Test the built image" 161 echo " push Push image to registry" 162 echo " all Build, test, and push" 163 echo 164 echo "Options:" 165 echo " --help, -h Show this help message" 166 echo " --engine ENGINE Container engine (podman|docker, default: podman)" 167 echo " --name NAME Image name (default: ferris-proof)" 168 echo " --tag TAG Image tag (default: latest)" 169 echo " --dockerfile FILE Containerfile to use (default: Containerfile.alpine)" 170 echo " --registry REGISTRY Registry to push to (optional)" 171 echo " --platform PLATFORM Target platform (default: linux/amd64)" 172 echo 173 echo "Environment Variables:" 174 echo " CONTAINER_ENGINE Container engine to use" 175 echo " IMAGE_NAME Image name" 176 echo " IMAGE_TAG Image tag" 177 echo " DOCKERFILE Containerfile path" 178 echo " REGISTRY Registry URL" 179 echo " PLATFORM Target platform" 180 echo 181 echo "Examples:" 182 echo " $0 build" 183 echo " $0 --engine docker --tag v1.0.0 build" 184 echo " $0 --registry ghcr.io/ferris-proof --tag latest all" 185 } 186 187 main() { 188 local command="build" 189 190 # Parse arguments 191 while [[ $# -gt 0 ]]; do 192 case $1 in 193 --help|-h) 194 show_usage 195 exit 0 196 ;; 197 --engine) 198 CONTAINER_ENGINE="$2" 199 shift 2 200 ;; 201 --name) 202 IMAGE_NAME="$2" 203 shift 2 204 ;; 205 --tag) 206 IMAGE_TAG="$2" 207 shift 2 208 ;; 209 --dockerfile) 210 DOCKERFILE="$2" 211 shift 2 212 ;; 213 --registry) 214 REGISTRY="$2" 215 shift 2 216 ;; 217 --platform) 218 PLATFORM="$2" 219 shift 2 220 ;; 221 build|test|push|all) 222 command="$1" 223 shift 224 ;; 225 *) 226 log_error "Unknown option: $1" 227 show_usage 228 exit 1 229 ;; 230 esac 231 done 232 233 check_container_engine 234 235 case $command in 236 build) 237 build_image 238 ;; 239 test) 240 test_image 241 ;; 242 push) 243 push_image 244 ;; 245 all) 246 build_image 247 test_image 248 push_image 249 ;; 250 *) 251 log_error "Unknown command: $command" 252 show_usage 253 exit 1 254 ;; 255 esac 256 257 log_success "Container operations completed successfully! 🎉" 258 } 259 260 main "$@"