Files
turmlibar-calendar/build-container.sh
2025-10-30 14:55:37 +01:00

300 lines
8.2 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Smart container build script for Turmli Bar Calendar
# Automatically detects architecture and chooses the best build strategy
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
IMAGE_NAME="${IMAGE_NAME:-turmli-calendar}"
BUILD_TYPE=""
RUNTIME=""
# Print functions
print_error() {
echo -e "${RED}$1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
# Detect container runtime
detect_runtime() {
if command -v podman &> /dev/null; then
RUNTIME="podman"
print_info "Using Podman"
elif command -v docker &> /dev/null; then
RUNTIME="docker"
print_info "Using Docker"
else
print_error "No container runtime found. Please install Podman or Docker."
exit 1
fi
}
# Detect architecture and choose build strategy
detect_architecture() {
ARCH=$(uname -m)
OS=$(uname -s)
print_info "System: ${OS} ${ARCH}"
case "${ARCH}" in
armv6l|armv7l)
print_info "ARM 32-bit detected (Raspberry Pi)"
BUILD_TYPE="arm"
;;
aarch64|arm64)
print_info "ARM 64-bit detected"
BUILD_TYPE="arm"
;;
x86_64|amd64)
print_info "x86_64 detected"
BUILD_TYPE="standard"
;;
*)
print_warning "Unknown architecture: ${ARCH}"
BUILD_TYPE="standard"
;;
esac
}
# Check if we have enough memory for build
check_memory() {
if [ -f /proc/meminfo ]; then
TOTAL_MEM=$(grep MemTotal /proc/meminfo | awk '{print $2}')
TOTAL_MEM_MB=$((TOTAL_MEM / 1024))
if [ $TOTAL_MEM_MB -lt 512 ]; then
print_warning "Low memory detected: ${TOTAL_MEM_MB}MB"
print_warning "Build may fail. Consider using pre-built images or increasing swap."
# Check swap
SWAP=$(grep SwapTotal /proc/meminfo | awk '{print $2}')
SWAP_MB=$((SWAP / 1024))
if [ $SWAP_MB -lt 1024 ]; then
print_warning "Swap is low: ${SWAP_MB}MB. Consider adding swap space:"
echo " sudo dd if=/dev/zero of=/swapfile bs=1G count=2"
echo " sudo mkswap /swapfile"
echo " sudo swapon /swapfile"
fi
else
print_info "Memory: ${TOTAL_MEM_MB}MB"
fi
fi
}
# Build for ARM architecture
build_arm() {
print_info "Building for ARM architecture..."
# Check which Dockerfile to use
if [ -f "Dockerfile.arm" ]; then
print_info "Using ARM-optimized Dockerfile"
DOCKERFILE="Dockerfile.arm"
else
print_warning "Dockerfile.arm not found, using standard Dockerfile"
print_warning "This may take longer and require more memory"
DOCKERFILE="Dockerfile"
fi
# Check if requirements-arm.txt exists
if [ -f "requirements-arm.txt" ] && [ -f "Dockerfile.arm" ]; then
print_info "Using simplified requirements for ARM"
elif [ -f "requirements-arm.txt" ]; then
print_warning "Found requirements-arm.txt but no Dockerfile.arm"
print_info "Consider creating Dockerfile.arm for better ARM support"
fi
# Build with limited parallelism on ARM to save memory
print_info "Building with limited parallelism to save memory..."
export CARGO_BUILD_JOBS=1
export MAKEFLAGS="-j1"
${RUNTIME} build \
--file "${DOCKERFILE}" \
--tag "${IMAGE_NAME}" \
--memory-swap -1 \
. || {
print_error "Build failed!"
print_info "Troubleshooting tips:"
echo " 1. Try increasing swap space"
echo " 2. Use Dockerfile.arm with requirements-arm.txt"
echo " 3. Build on a more powerful machine and transfer the image"
exit 1
}
}
# Build for standard architecture
build_standard() {
print_info "Building for standard architecture..."
# Choose Dockerfile
if [ "$RUNTIME" = "podman" ] && [ -f "Containerfile" ]; then
DOCKERFILE="Containerfile"
elif [ -f "Dockerfile" ]; then
DOCKERFILE="Dockerfile"
else
print_error "No Dockerfile found!"
exit 1
fi
print_info "Using ${DOCKERFILE}"
${RUNTIME} build \
--file "${DOCKERFILE}" \
--tag "${IMAGE_NAME}" \
. || {
print_error "Build failed!"
exit 1
}
}
# Build with cache mount (if supported)
build_with_cache() {
print_info "Attempting build with cache mount..."
# Check if BuildKit is available (Docker) or if Podman supports cache mounts
if [ "$RUNTIME" = "docker" ]; then
export DOCKER_BUILDKIT=1
CACHE_OPT="--mount=type=cache,target=/root/.cache/pip"
elif [ "$RUNTIME" = "podman" ]; then
# Podman 4.1+ supports cache mounts
CACHE_OPT="--mount=type=cache,target=/root/.cache/pip"
else
CACHE_OPT=""
fi
# Attempt build with cache
if [ -n "$CACHE_OPT" ]; then
print_info "Using build cache for faster rebuilds"
fi
if [ "$BUILD_TYPE" = "arm" ]; then
build_arm
else
build_standard
fi
}
# Clean build (no cache)
clean_build() {
print_info "Performing clean build (no cache)..."
${RUNTIME} build \
--no-cache \
--file "${DOCKERFILE:-Dockerfile}" \
--tag "${IMAGE_NAME}" \
. || {
print_error "Build failed!"
exit 1
}
}
# Show build information
show_info() {
echo -e "${BLUE}Build Configuration:${NC}"
echo " Runtime: ${RUNTIME}"
echo " Architecture: $(uname -m)"
echo " Build Type: ${BUILD_TYPE}"
echo " Image Name: ${IMAGE_NAME}"
if [ "$BUILD_TYPE" = "arm" ]; then
echo ""
echo -e "${YELLOW}ARM Build Notes:${NC}"
echo " - Uses simplified dependencies where possible"
echo " - Avoids packages requiring Rust compilation"
echo " - May have slightly reduced performance"
echo " - Optimized for low memory usage"
fi
echo ""
print_info "Checking available Dockerfiles..."
for file in Dockerfile Containerfile Dockerfile.arm; do
if [ -f "$file" ]; then
print_success "$file found"
fi
done
echo ""
print_info "Checking requirements files..."
for file in requirements.txt requirements-arm.txt; do
if [ -f "$file" ]; then
print_success "$file found"
fi
done
}
# Main function
main() {
case "${1:-}" in
--clean)
detect_runtime
detect_architecture
clean_build
;;
--info)
detect_runtime
detect_architecture
check_memory
show_info
;;
--help)
echo "Smart Container Build Script for Turmli Bar Calendar"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --clean Perform a clean build (no cache)"
echo " --info Show build configuration and system info"
echo " --help Show this help message"
echo ""
echo "Environment Variables:"
echo " IMAGE_NAME Name for the built image (default: turmli-calendar)"
echo ""
echo "The script automatically detects:"
echo " - Container runtime (Podman/Docker)"
echo " - System architecture (ARM/x86_64)"
echo " - Available memory"
echo " - Best Dockerfile to use"
;;
*)
detect_runtime
detect_architecture
check_memory
print_info "Starting build process..."
if [ "$BUILD_TYPE" = "arm" ]; then
build_arm
else
build_standard
fi
if [ $? -eq 0 ]; then
print_success "Build completed successfully!"
print_info "Image: ${IMAGE_NAME}"
print_info "Run with: ${RUNTIME} run -d -p 8000:8000 ${IMAGE_NAME}"
fi
;;
esac
}
# Run main function
main "$@"