This project supports building container images for multiple CPU architectures:
- amd64 (x86_64) - Intel/AMD processors
- arm64 (aarch64) - Apple Silicon, AWS Graviton, Raspberry Pi 4+
- s390x - IBM Z mainframes
# Build for your local architecture only
make container-build
# Validate multiplatform build (all 3 architectures)
make container-build-multi
# Build and push to a registry
make container-build-multi REGISTRY=ghcr.io/your-org
# Inspect a multiplatform manifest
make container-inspect-manifest REGISTRY=ghcr.io/ibm/mcp-context-forge:latest| File | Base Image | Platforms | Size | Use Case |
|---|---|---|---|---|
Containerfile.lite |
ubi10-minimal | amd64, arm64, s390x | ~150MB | Multiplatform builds, CI/CD |
Containerfile.scratch |
scratch | amd64 only* | ~100MB | Smallest possible image |
*Containerfile.scratch uses dnf --installroot which fails under QEMU emulation, so it only works for native builds.
make container-build CONTAINER_FILE=Containerfile.scratchThe local Docker daemon can only store images for one architecture at a time. When you run:
make container-buildIt builds an image for your current machine's architecture and loads it into Docker.
Multiplatform images are manifest lists - an index pointing to multiple platform-specific images stored in a registry. They cannot be stored locally.
# This validates the build works for all platforms (cached in buildx)
make container-build-multi
# This builds AND pushes to a registry
make container-build-multi REGISTRY=localhost:5000When someone pulls the image, Docker automatically selects the correct architecture:
# On amd64 machine - pulls amd64 image
docker pull ghcr.io/ibm/mcp-context-forge:latest
# On arm64 machine - pulls arm64 image
docker pull ghcr.io/ibm/mcp-context-forge:latest
# On s390x machine - pulls s390x image
docker pull ghcr.io/ibm/mcp-context-forge:latestThe .github/workflows/docker-multiplatform.yml workflow:
- Lints the Dockerfile with Hadolint
- Builds each platform in parallel:
- amd64 on
ubuntu-latest(native) - arm64 on
ubuntu-24.04-arm(native) - s390x on
ubuntu-latestwith QEMU (emulated, slower)
- amd64 on
- Creates a multiplatform manifest
- Scans for vulnerabilities (Trivy, Grype)
- Signs with Cosign (keyless OIDC)
| Platform | Runner | Estimated Time |
|---|---|---|
| amd64 | Native | ~5-8 min |
| arm64 | Native | ~5-8 min |
| s390x | QEMU | ~30-45 min |
The s390x architecture requires OpenSSL instead of BoringSSL for grpcio. This is handled automatically in the Containerfile:
RUN if [ `uname -m` = "s390x" ]; then \
echo "export GRPC_PYTHON_BUILD_SYSTEM_OPENSSL='True'" > /etc/profile.d/use-openssl.sh; \
fiThe original Containerfile.scratch used dnf --installroot to create a minimal rootfs from scratch. This approach:
- Produces the smallest possible image (~100MB)
- Keeps the RPM database for security scanning
- Fails under QEMU emulation (dnf spawns subprocesses that QEMU can't handle)
The Containerfile.lite uses ubi10-minimal as the runtime base:
- Slightly larger (~150MB) but still minimal
- Works with QEMU emulation for cross-platform builds
- Uses
microdnfwhich is more QEMU-friendly - Maintains RPM database for security scanning
# Using make
make container-inspect-manifest REGISTRY=ghcr.io/ibm/mcp-context-forge:latest
# Using docker directly
docker buildx imagetools inspect ghcr.io/ibm/mcp-context-forge:latestExample output:
Name: ghcr.io/ibm/mcp-context-forge:latest
MediaType: application/vnd.oci.image.index.v1+json
Digest: sha256:abc123...
Manifests:
Name: ghcr.io/ibm/mcp-context-forge:latest@sha256:def456...
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/amd64
Name: ghcr.io/ibm/mcp-context-forge:latest@sha256:ghi789...
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/arm64
Name: ghcr.io/ibm/mcp-context-forge:latest@sha256:jkl012...
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/s390x
To test multiplatform images locally:
# Start a local registry
docker run -d -p 5000:5000 --name registry registry:2
# Build and push
make container-build-multi REGISTRY=localhost:5000
# Inspect
make container-inspect-manifest REGISTRY=localhost:5000/mcpgateway/mcpgateway:latest
# Pull specific platform
docker pull --platform linux/arm64 localhost:5000/mcpgateway/mcpgateway:latestIf you see errors like:
ERROR: process "/dev/.buildkit_qemu_emulator /bin/bash ..." did not complete successfully
This usually means a command doesn't work under QEMU emulation. The Containerfile.lite is designed to avoid these issues by using ubi10-minimal + microdnf.
# Create the builder
docker buildx create --name mcpgateway-builder --driver docker-container
# Use it
docker buildx use mcpgateway-builderBuildx caches can grow large. Clean them:
docker buildx prune -f