Skip to main content
Glama
build-multiarch.sh8.7 kB
#!/bin/bash # MCP Rubber Duck - Multi-Architecture Build Script # This script builds Docker images for multiple architectures including Raspberry Pi set -euo pipefail # 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:-mcp-rubber-duck}" IMAGE_TAG="${IMAGE_TAG:-latest}" DOCKER_REGISTRY="${DOCKER_REGISTRY:-}" PUSH_IMAGE="${PUSH_IMAGE:-false}" USE_GITHUB="${USE_GITHUB:-false}" # Supported platforms for Raspberry Pi (Pi 3+ supports ARM64) PLATFORMS="linux/amd64,linux/arm64" # Functions log() { echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}" } warn() { echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}" } error() { echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}" exit 1 } info() { echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] INFO: $1${NC}" } print_usage() { cat << EOF Usage: $0 [OPTIONS] Build multi-architecture Docker images for MCP Rubber Duck OPTIONS: -n, --name NAME Docker image name (default: mcp-rubber-duck) -t, --tag TAG Docker image tag (default: latest) -r, --registry REGISTRY Docker registry (e.g., your-username, ghcr.io/username) -p, --push Push image to registry after build --gh, --github Use GitHub Container Registry (ghcr.io) with gh CLI --local Build for local architecture only (faster) --arm-only Build for ARM architectures only (Pi optimized) -h, --help Show this help message EXAMPLES: # Build for all architectures locally $0 --name mcp-rubber-duck --tag v1.0.0 # Build and push to Docker Hub $0 --name yourusername/mcp-rubber-duck --push # Build and push to GitHub Container Registry $0 --registry ghcr.io/yourusername --push # Build and push to GitHub (auto-detects username) $0 --github --push # Build only for Raspberry Pi (ARM) $0 --arm-only --name mcp-rubber-duck-arm # Build for local development (current architecture only) $0 --local ENVIRONMENT VARIABLES: IMAGE_NAME Override default image name IMAGE_TAG Override default tag DOCKER_REGISTRY Override default registry PUSH_IMAGE Set to 'true' to push after build USE_GITHUB Set to 'true' to use GitHub Container Registry EOF } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -n|--name) IMAGE_NAME="$2" shift 2 ;; -t|--tag) IMAGE_TAG="$2" shift 2 ;; -r|--registry) DOCKER_REGISTRY="$2" shift 2 ;; -p|--push) PUSH_IMAGE="true" shift ;; --gh|--github) USE_GITHUB="true" shift ;; --local) PLATFORMS="" shift ;; --arm-only) PLATFORMS="linux/arm64,linux/arm/v7" shift ;; -h|--help) print_usage exit 0 ;; *) error "Unknown option: $1" ;; esac done # GitHub CLI integration if [[ "$USE_GITHUB" == "true" ]]; then # Check if gh is installed if ! command -v gh &> /dev/null; then error "GitHub CLI (gh) is not installed. Install from: https://cli.github.com/" fi # Check if user is authenticated if ! gh auth status &> /dev/null; then error "Not authenticated with GitHub. Run: gh auth login" fi # Get GitHub username GITHUB_USER=$(gh api user --jq .login 2>/dev/null) if [[ -z "$GITHUB_USER" ]]; then error "Could not get GitHub username. Check your gh authentication." fi # Get repository name (fallback to mcp-rubber-duck) REPO_NAME=$(gh repo view --json name --jq .name 2>/dev/null || echo "mcp-rubber-duck") # Set up GitHub Container Registry DOCKER_REGISTRY="ghcr.io/$GITHUB_USER" IMAGE_NAME="$REPO_NAME" PUSH_IMAGE="true" # Auto-enable push for GitHub log "Using GitHub Container Registry: ghcr.io/$GITHUB_USER/$REPO_NAME" # Authenticate Docker with ghcr.io using gh info "Authenticating Docker with GitHub Container Registry..." if ! gh auth token | docker login ghcr.io -u "$GITHUB_USER" --password-stdin; then error "Failed to authenticate Docker with ghcr.io" fi fi # Build full image name if [[ -n "$DOCKER_REGISTRY" ]]; then FULL_IMAGE_NAME="${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}" else FULL_IMAGE_NAME="${IMAGE_NAME}:${IMAGE_TAG}" fi # Validate Docker is installed if ! command -v docker &> /dev/null; then error "Docker is not installed or not in PATH" fi # Check if buildx is available if ! docker buildx version &> /dev/null; then error "Docker buildx is not available. Please update Docker to a newer version." fi # Change to project root directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" cd "$PROJECT_ROOT" log "Starting multi-architecture build for MCP Rubber Duck" info "Image name: $FULL_IMAGE_NAME" info "Platforms: ${PLATFORMS:-$(uname -m)}" info "Push to registry: $PUSH_IMAGE" # Check if Dockerfile exists if [[ ! -f "Dockerfile" ]]; then error "Dockerfile not found in project root" fi # Create buildx builder if it doesn't exist BUILDER_NAME="mcp-multiarch" if ! docker buildx inspect "$BUILDER_NAME" &> /dev/null; then log "Creating buildx builder: $BUILDER_NAME" docker buildx create --name "$BUILDER_NAME" --platform "$PLATFORMS" --use else log "Using existing buildx builder: $BUILDER_NAME" docker buildx use "$BUILDER_NAME" fi # Ensure builder is running log "Starting buildx builder" docker buildx inspect --bootstrap # Build command BUILD_ARGS=( "buildx" "build" "--builder" "$BUILDER_NAME" "-t" "$FULL_IMAGE_NAME" "--progress" "plain" ) # Add platform specification if not local build if [[ -n "$PLATFORMS" ]]; then BUILD_ARGS+=("--platform" "$PLATFORMS") fi # Add push flag if requested if [[ "$PUSH_IMAGE" == "true" ]]; then BUILD_ARGS+=("--push") info "Image will be pushed to registry after build" else BUILD_ARGS+=("--load") info "Image will be loaded to local Docker daemon" fi # Add context BUILD_ARGS+=(".") # Print build command for debugging info "Build command: docker ${BUILD_ARGS[*]}" # Run the build log "Building Docker image..." if docker "${BUILD_ARGS[@]}"; then log "✅ Build completed successfully!" if [[ "$PUSH_IMAGE" == "true" ]]; then log "✅ Image pushed to registry: $FULL_IMAGE_NAME" # Show GitHub package info if using GitHub if [[ "$USE_GITHUB" == "true" ]]; then log "📦 GitHub Package Information:" if gh api "user/packages/container/$IMAGE_NAME" &> /dev/null; then echo " Package URL: https://github.com/$GITHUB_USER/packages/container/package/$IMAGE_NAME" echo " Visibility: $(gh api "user/packages/container/$IMAGE_NAME" --jq .visibility)" echo " Downloads: $(gh api "user/packages/container/$IMAGE_NAME/versions" --jq 'map(.metadata.container.tags | length) | add')" # Show how to make package public if it's private VISIBILITY=$(gh api "user/packages/container/$IMAGE_NAME" --jq .visibility 2>/dev/null) if [[ "$VISIBILITY" == "private" ]]; then info "To make package public: gh api --method PATCH user/packages/container/$IMAGE_NAME --field visibility=public" fi else warn "Package info not yet available (may take a moment to appear)" fi fi else log "✅ Image loaded locally: $FULL_IMAGE_NAME" # Show image info if [[ -z "$PLATFORMS" ]]; then info "Image details:" docker images "$FULL_IMAGE_NAME" | head -2 fi fi # Show next steps echo log "🚀 Next steps for Raspberry Pi deployment:" echo " 1. Copy this image to your Raspberry Pi:" if [[ "$PUSH_IMAGE" == "true" ]]; then echo " docker pull $FULL_IMAGE_NAME" else echo " docker save $FULL_IMAGE_NAME | ssh pi@your-pi-ip 'docker load'" fi echo " 2. Use docker-compose.yml to deploy (works on all platforms)" echo " 3. Configure your .env file with API keys" else error "❌ Build failed!" fi # Cleanup log "Build process completed"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nesquikm/mcp-rubber-duck'

If you have feedback or need assistance with the MCP directory API, please join our Discord server