Building WAIIDE on M2 Mac for ECS Deployment

Building WAIIDE on M2 Mac for ECS Deployment

Calliope Integration: This component is integrated into the Calliope AI platform. Some features and configurations may differ from the upstream project.

The Problem

M2 Macs use ARM64 architecture, but ECS runs on AMD64 (x86_64). When you build on M2 without specifying platform, Docker builds for ARM64 by default, causing runtime failures on ECS.

Symptoms

  • Build succeeds on M2 Mac
  • Same build works on GitHub Actions (amd64)
  • ECS fails with missing files:
    • Cannot find module '/home/calliope/WAIIDE-server/out/server-main.js'
    • cannot stat '/home/calliope/scripts/jupyter_server_config.py'

Solution: Cross-Platform Build on M2

1. Setup Docker Buildx

# Create and use a new builder instance
docker buildx create --name multiarch --use
docker buildx inspect --bootstrap

# Verify it supports linux/amd64
docker buildx ls

2. Build for AMD64 Architecture

# CRITICAL: Always specify --platform linux/amd64
docker buildx build \
  --platform linux/amd64 \
  --load \
  -t calliopeai/waiide:latest-amd64 \
  .

3. Verify Architecture Before Pushing

# Check the image architecture
docker inspect calliopeai/waiide:latest-amd64 | grep Architecture
# Should show: "Architecture": "amd64"

# Test the image (will be slow on M2 due to emulation)
docker run --rm --platform linux/amd64 calliopeai/waiide:latest-amd64 uname -m
# Should output: x86_64

4. Push to Registry

# Push specifically the amd64 image
docker buildx build \
  --platform linux/amd64 \
  --push \
  -t your-registry/waiide:latest \
  .

Common M2 Build Issues

Issue 1: Build Fails with Node.js Errors

Native dependencies might fail during cross-compilation:

# Use Docker's built-in QEMU emulation
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

# Then rebuild
docker buildx build --platform linux/amd64 ...

Issue 2: Extremely Slow Build

Cross-compilation is slow. Options:

  1. Use GitHub Actions for builds (recommended)
  2. Use a remote amd64 builder:
# Set up remote Docker context
docker context create remote --docker "host=ssh://user@amd64-server"
docker context use remote
docker build -t calliopeai/waiide:latest .

Issue 3: Wrong Platform in Compose

# compose.yml - specify platform
services:
  calliope-ide:
    platform: linux/amd64  # Add this line
    build:
      context: .
      dockerfile: Dockerfile
      platforms:
        - linux/amd64

Best Practices for M2 Development

1. Always Tag with Architecture

# Clear naming convention
docker buildx build --platform linux/amd64 -t waiide:latest-amd64 .
docker buildx build --platform linux/arm64 -t waiide:latest-arm64 .

2. Local Development vs Production

# For local M2 development (fast)
docker build -t waiide:dev .  # Uses native arm64

# For ECS deployment (slow but necessary)
docker buildx build --platform linux/amd64 -t waiide:prod .

3. Verification Script

Create verify-build.sh:

#!/bin/bash
IMAGE=${1:-calliopeai/waiide:latest}

echo "Checking image: $IMAGE"
docker run --rm --platform linux/amd64 $IMAGE bash -c "
  echo '=== Architecture ==='
  uname -m
  echo '=== WAIIDE Server ==='
  ls -la /home/calliope/WAIIDE-server/server-main.js 2>/dev/null || \
  ls -la /home/calliope/WAIIDE-server/out/server-main.js 2>/dev/null || \
  echo 'ERROR: server-main.js not found!'
  echo '=== Scripts ==='
  ls -la /home/calliope/scripts/jupyter_server_config.py || \
  echo 'ERROR: Scripts missing!'
"

GitHub Actions Alternative

For consistent builds, use GitHub Actions:

name: Build and Push WAIIDE

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest  # Always amd64
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          platforms: linux/amd64
          push: true
          tags: your-registry/waiide:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

Quick Fix for Current Situation

# On your M2 Mac, rebuild for amd64
docker buildx build \
  --platform linux/amd64 \
  --no-cache \
  --push \
  -t your-registry/waiide:latest-amd64 \
  .

# Update ECS task definition to use explicit tag
"image": "your-registry/waiide:latest-amd64"

# Force ECS to pull new image
aws ecs update-service --cluster your-cluster --service your-service --force-new-deployment

Debugging Commands

# Check what architecture your current image is
docker image inspect calliopeai/waiide:latest --format '{{.Architecture}}'

# List all images with architecture
docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.Architecture}}"

# Test ECS-bound image locally
docker run --rm --platform linux/amd64 your-registry/waiide:latest \
  bash -c "uname -m && ls -la /home/calliope/WAIIDE-server/"

TL;DR

Always use --platform linux/amd64 when building on M2 Mac for ECS deployment!