docker-publish.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #!/bin/bash
  2. # Build and push multi-architecture Docker image to GitHub Container Registry
  3. #
  4. # Usage:
  5. # ./docker-publish.sh [version] [--parallel]
  6. #
  7. # Examples:
  8. # ./docker-publish.sh 0.1.7b # Sequential build (default)
  9. # ./docker-publish.sh 0.1.7b --parallel # Build both archs simultaneously
  10. #
  11. # Note: All versions are also tagged as 'latest'
  12. #
  13. # Prerequisites:
  14. # 1. Log in to ghcr.io first:
  15. # echo $GITHUB_TOKEN | docker login ghcr.io -u YOUR_USERNAME --password-stdin
  16. #
  17. # 2. Create a GitHub Personal Access Token with 'write:packages' scope:
  18. # https://github.com/settings/tokens/new?scopes=write:packages
  19. #
  20. # Supported architectures:
  21. # - linux/amd64 (x86_64, most servers/desktops)
  22. # - linux/arm64 (Raspberry Pi 4/5, Apple Silicon via emulation)
  23. set -e
  24. # Configuration
  25. REGISTRY="ghcr.io"
  26. IMAGE_NAME="maziggy/bambuddy"
  27. FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}"
  28. PLATFORMS="linux/amd64,linux/arm64"
  29. BUILDER_NAME="bambuddy-builder"
  30. # Colors for output
  31. RED='\033[0;31m'
  32. GREEN='\033[0;32m'
  33. YELLOW='\033[1;33m'
  34. BLUE='\033[0;34m'
  35. NC='\033[0m' # No Color
  36. # Parse arguments
  37. VERSION=""
  38. PARALLEL=false
  39. for arg in "$@"; do
  40. case $arg in
  41. --parallel)
  42. PARALLEL=true
  43. ;;
  44. *)
  45. if [ -z "$VERSION" ]; then
  46. VERSION="$arg"
  47. fi
  48. ;;
  49. esac
  50. done
  51. if [ -z "$VERSION" ]; then
  52. echo -e "${YELLOW}Usage: $0 <version> [--parallel]${NC}"
  53. echo "Example: $0 0.1.6"
  54. echo " $0 0.1.6 --parallel # Build both architectures simultaneously"
  55. exit 1
  56. fi
  57. # Get CPU count
  58. CPU_COUNT=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
  59. echo -e "${GREEN}================================================${NC}"
  60. echo -e "${GREEN} Building multi-arch image${NC}"
  61. echo -e "${GREEN} ${FULL_IMAGE}:${VERSION}${NC}"
  62. echo -e "${GREEN} Platforms: ${PLATFORMS}${NC}"
  63. echo -e "${GREEN} CPU cores: ${CPU_COUNT}${NC}"
  64. if [ "$PARALLEL" = true ]; then
  65. echo -e "${GREEN} Mode: PARALLEL (both archs simultaneously)${NC}"
  66. else
  67. echo -e "${GREEN} Mode: Sequential (amd64 → arm64)${NC}"
  68. fi
  69. echo -e "${GREEN}================================================${NC}"
  70. echo ""
  71. # Check if logged in to ghcr.io
  72. if ! grep -q "ghcr.io" ~/.docker/config.json 2>/dev/null; then
  73. echo -e "${YELLOW}Warning: You may not be logged in to ghcr.io${NC}"
  74. echo "Run: echo \$GITHUB_TOKEN | docker login ghcr.io -u YOUR_USERNAME --password-stdin"
  75. echo ""
  76. fi
  77. # Always tag as latest (in addition to version tag)
  78. # Setup buildx builder if not exists
  79. echo -e "${BLUE}[1/4] Setting up Docker Buildx...${NC}"
  80. if ! docker buildx inspect "$BUILDER_NAME" >/dev/null 2>&1; then
  81. echo "Creating new buildx builder: $BUILDER_NAME (optimized for ${CPU_COUNT} cores)"
  82. docker buildx create \
  83. --name "$BUILDER_NAME" \
  84. --driver docker-container \
  85. --driver-opt network=host \
  86. --driver-opt "env.BUILDKIT_STEP_LOG_MAX_SIZE=10000000" \
  87. --buildkitd-flags "--allow-insecure-entitlement network.host --oci-worker-gc=false" \
  88. --config /dev/stdin <<EOF
  89. [worker.oci]
  90. max-parallelism = ${CPU_COUNT}
  91. EOF
  92. docker buildx inspect --bootstrap "$BUILDER_NAME"
  93. fi
  94. docker buildx use "$BUILDER_NAME"
  95. # Verify builder supports multi-platform
  96. echo -e "${BLUE}[2/4] Verifying multi-platform support...${NC}"
  97. if ! docker buildx inspect --bootstrap | grep -q "linux/arm64"; then
  98. echo -e "${YELLOW}Installing QEMU for cross-platform builds...${NC}"
  99. docker run --privileged --rm tonistiigi/binfmt --install all
  100. fi
  101. # Build tags (always include latest)
  102. TAGS="-t ${FULL_IMAGE}:${VERSION} -t ${FULL_IMAGE}:latest"
  103. echo -e "${BLUE}[3/4] Building and pushing (version + latest)...${NC}"
  104. # Common build args (no cache to ensure clean builds)
  105. BUILD_ARGS="--provenance=false --sbom=false --no-cache --pull"
  106. if [ "$PARALLEL" = true ]; then
  107. # Parallel build: Build each architecture separately then combine
  108. echo -e "${YELLOW}Building amd64 and arm64 in parallel (${CPU_COUNT} cores each, no cache)...${NC}"
  109. # Build amd64 in background
  110. (
  111. echo -e "${BLUE}[amd64] Starting build...${NC}"
  112. docker buildx build \
  113. --platform linux/amd64 \
  114. -t "${FULL_IMAGE}:${VERSION}-amd64" \
  115. ${BUILD_ARGS} \
  116. --push \
  117. . 2>&1 | sed 's/^/[amd64] /'
  118. echo -e "${GREEN}[amd64] Complete!${NC}"
  119. ) &
  120. PID_AMD64=$!
  121. # Build arm64 in background
  122. (
  123. echo -e "${BLUE}[arm64] Starting build...${NC}"
  124. docker buildx build \
  125. --platform linux/arm64 \
  126. -t "${FULL_IMAGE}:${VERSION}-arm64" \
  127. ${BUILD_ARGS} \
  128. --push \
  129. . 2>&1 | sed 's/^/[arm64] /'
  130. echo -e "${GREEN}[arm64] Complete!${NC}"
  131. ) &
  132. PID_ARM64=$!
  133. # Wait for both builds
  134. echo "Waiting for parallel builds to complete..."
  135. wait $PID_AMD64
  136. wait $PID_ARM64
  137. # Create and push multi-arch manifest (version + latest)
  138. echo -e "${BLUE}Creating multi-arch manifest...${NC}"
  139. docker buildx imagetools create \
  140. -t "${FULL_IMAGE}:${VERSION}" \
  141. -t "${FULL_IMAGE}:latest" \
  142. "${FULL_IMAGE}:${VERSION}-amd64" \
  143. "${FULL_IMAGE}:${VERSION}-arm64"
  144. else
  145. # Sequential build (default): Build both platforms in one command
  146. echo -e "${YELLOW}Building sequentially with ${CPU_COUNT} cores (no cache)...${NC}"
  147. DOCKER_BUILDKIT=1 docker buildx build \
  148. --platform "$PLATFORMS" \
  149. ${BUILD_ARGS} \
  150. $TAGS \
  151. --push \
  152. .
  153. fi
  154. echo -e "${BLUE}[4/4] Verifying manifest...${NC}"
  155. docker buildx imagetools inspect "${FULL_IMAGE}:${VERSION}"
  156. echo ""
  157. echo -e "${GREEN}================================================${NC}"
  158. echo -e "${GREEN}✓ Successfully pushed multi-arch image:${NC}"
  159. echo -e "${GREEN}================================================${NC}"
  160. echo " - ${FULL_IMAGE}:${VERSION}"
  161. echo " - ${FULL_IMAGE}:latest"
  162. echo ""
  163. echo -e "${BLUE}Supported platforms:${NC}"
  164. echo " - linux/amd64 (Intel/AMD servers, desktops)"
  165. echo " - linux/arm64 (Raspberry Pi 4/5, Apple Silicon)"
  166. echo ""
  167. echo -e "${GREEN}Users can now run:${NC}"
  168. echo " docker pull ${FULL_IMAGE}:${VERSION}"