#!/usr/bin/env bash # # push-to-dockerhub.sh - Build and push Docker image to DockerHub # # This script builds a Docker image for ktransformers with standardized naming # and pushes it to DockerHub with both full and simplified tags. # # Features: # - Automatic version detection # - Standardized naming convention # - Multi-CPU variant support (AMX/AVX512/AVX2) # - Full and simplified tag support # - Retry logic for network failures # - Comprehensive error handling # # Usage: # ./push-to-dockerhub.sh [OPTIONS] # # Example: # ./push-to-dockerhub.sh \ # --cuda-version 12.8.1 \ # --repository kvcache/ktransformers \ # --also-push-simplified set -euo pipefail # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Source utility functions # shellcheck source=docker-utils.sh source "$SCRIPT_DIR/docker-utils.sh" ################################################################################ # Default Configuration ################################################################################ # Build parameters CUDA_VERSION="12.8.1" UBUNTU_MIRROR="0" HTTP_PROXY="" HTTPS_PROXY="" CPU_VARIANT="x86-intel-multi" FUNCTIONALITY="sft" # Paths DOCKERFILE="$SCRIPT_DIR/Dockerfile" CONTEXT_DIR="$SCRIPT_DIR" # Registry settings REGISTRY="docker.io" REPOSITORY="" # Must be provided by user # Options DRY_RUN=false SKIP_BUILD=false ALSO_PUSH_SIMPLIFIED=false MAX_RETRIES=3 RETRY_DELAY=5 EXTRA_BUILD_ARGS=() ################################################################################ # Help Message ################################################################################ usage() { cat <&2 log_info "Temporary tag: $temp_tag" >&2 # Prepare build arguments local build_args=() build_args+=("--build-arg" "CUDA_VERSION=$CUDA_VERSION") build_args+=("--build-arg" "UBUNTU_MIRROR=$UBUNTU_MIRROR") build_args+=("--build-arg" "CPU_VARIANT=$CPU_VARIANT") build_args+=("--build-arg" "BUILD_ALL_CPU_VARIANTS=1") # Add proxy settings if provided if [ -n "$HTTP_PROXY" ]; then build_args+=("--build-arg" "HTTP_PROXY=$HTTP_PROXY") fi if [ -n "$HTTPS_PROXY" ]; then build_args+=("--build-arg" "HTTPS_PROXY=$HTTPS_PROXY") fi # Add extra build args build_args+=("${EXTRA_BUILD_ARGS[@]}") # Add network host build_args+=("--network" "host") # Build command local build_cmd=( docker build -f "$DOCKERFILE" "${build_args[@]}" -t "$temp_tag" "$CONTEXT_DIR" ) # Display build command { log_info "Build command:" echo " ${build_cmd[*]}" } >&2 if [ "$DRY_RUN" = true ]; then log_warning "DRY RUN: Skipping actual build" >&2 return 0 fi # Execute build log_info "Starting Docker build (this may take 30-60 minutes)..." >&2 if "${build_cmd[@]}" >&2; then log_success "Docker image built successfully" >&2 echo "$temp_tag" else log_error "Docker build failed" >&2 exit 1 fi } ################################################################################ # Generate Tags ################################################################################ generate_tags() { local image_tag="$1" local timestamp="$2" if [ "$DRY_RUN" = true ]; then log_warning "DRY RUN: Using placeholder versions" # Use placeholder versions for dry run local versions="SGLANG_VERSION=0.5.6 KTRANSFORMERS_VERSION=0.4.3 LLAMAFACTORY_VERSION=0.9.3" else # Extract versions from image local versions versions=$(extract_versions_from_image "$image_tag") if [ $? -ne 0 ]; then log_error "Failed to extract versions from image" exit 1 fi # Validate versions if ! validate_versions "$versions"; then log_error "Version validation failed" exit 1 fi fi # Generate full tag local full_tag full_tag=$(generate_image_name "$versions" "$CUDA_VERSION" "$CPU_VARIANT" "$FUNCTIONALITY" "$timestamp") if [ -z "$full_tag" ]; then log_error "Failed to generate image name" exit 1 fi echo "FULL_TAG=$full_tag" # Generate simplified tag if requested if [ "$ALSO_PUSH_SIMPLIFIED" = true ]; then local ktrans_ver ktrans_ver=$(echo "$versions" | grep "^KTRANSFORMERS_VERSION=" | cut -d= -f2) local simplified_tag simplified_tag=$(generate_simplified_tag "$ktrans_ver" "$CUDA_VERSION") echo "SIMPLIFIED_TAG=$simplified_tag" fi } ################################################################################ # Push to Registry ################################################################################ push_image_with_retry() { local source_tag="$1" local target_tag="$2" local attempt=1 log_step "Pushing image: $target_tag" if [ "$DRY_RUN" = true ]; then log_warning "DRY RUN: Skipping actual push" log_info "Would execute:" echo " docker tag $source_tag $target_tag" echo " docker push $target_tag" return 0 fi # Tag the image log_info "Tagging image..." if ! docker tag "$source_tag" "$target_tag"; then log_error "Failed to tag image" return 1 fi # Push with retry logic while [ $attempt -le "$MAX_RETRIES" ]; do log_info "Push attempt $attempt/$MAX_RETRIES..." if docker push "$target_tag"; then log_success "Successfully pushed: $target_tag" return 0 else log_warning "Push failed (attempt $attempt/$MAX_RETRIES)" if [ $attempt -lt "$MAX_RETRIES" ]; then log_info "Retrying in ${RETRY_DELAY} seconds..." sleep "$RETRY_DELAY" fi ((attempt++)) fi done log_error "Failed to push after $MAX_RETRIES attempts" return 1 } ################################################################################ # Main ################################################################################ main() { log_step "KTransformers Docker Image Build and Push" # Parse arguments parse_args "$@" # Validate configuration validate_config # Generate timestamp TIMESTAMP=$(get_beijing_timestamp) log_info "Build timestamp: $TIMESTAMP" # Display configuration display_summary "Push Configuration" \ "CUDA Version: $CUDA_VERSION" \ "Ubuntu Mirror: $UBUNTU_MIRROR" \ "CPU Variant: $CPU_VARIANT" \ "Functionality: $FUNCTIONALITY" \ "Registry: $REGISTRY" \ "Repository: $REPOSITORY" \ "Push Simplified: $ALSO_PUSH_SIMPLIFIED" \ "Skip Build: $SKIP_BUILD" \ "HTTP Proxy: ${HTTP_PROXY:-}" \ "HTTPS Proxy: ${HTTPS_PROXY:-}" \ "Dockerfile: $DOCKERFILE" \ "Context Dir: $CONTEXT_DIR" \ "Timestamp: $TIMESTAMP" \ "Dry Run: $DRY_RUN" # Build image TEMP_TAG=$(build_image) if [ "$DRY_RUN" = true ]; then TEMP_TAG="ktransformers:temp-dryrun" fi # Generate tags log_step "Generating tags" TAG_INFO=$(generate_tags "$TEMP_TAG" "$TIMESTAMP") # Parse tag info FULL_TAG=$(echo "$TAG_INFO" | grep "^FULL_TAG=" | cut -d= -f2) SIMPLIFIED_TAG=$(echo "$TAG_INFO" | grep "^SIMPLIFIED_TAG=" | cut -d= -f2 || echo "") log_info "Full tag: $FULL_TAG" if [ -n "$SIMPLIFIED_TAG" ]; then log_info "Simplified tag: $SIMPLIFIED_TAG" fi # Push full tag FULL_IMAGE="$REGISTRY/$REPOSITORY:$FULL_TAG" if ! push_image_with_retry "$TEMP_TAG" "$FULL_IMAGE"; then log_error "Failed to push full tag" exit 1 fi # Push simplified tag if requested if [ -n "$SIMPLIFIED_TAG" ]; then SIMPLIFIED_IMAGE="$REGISTRY/$REPOSITORY:$SIMPLIFIED_TAG" if ! push_image_with_retry "$TEMP_TAG" "$SIMPLIFIED_IMAGE"; then log_warning "Failed to push simplified tag, but continuing..." fi fi # Cleanup temporary image if [ "$DRY_RUN" = false ]; then log_step "Cleaning up temporary image" cleanup_temp_images "$TEMP_TAG" fi # Display summary local summary_lines=( "Successfully pushed images:" "" "Full tag:" " $FULL_IMAGE" "" ) if [ -n "$SIMPLIFIED_TAG" ]; then summary_lines+=( "Simplified tag:" " $SIMPLIFIED_IMAGE" "" ) fi summary_lines+=( "To pull the image:" " docker pull $FULL_IMAGE" "" "To run the container:" " docker run -it --rm $FULL_IMAGE /bin/bash" ) display_summary "Push Complete" "${summary_lines[@]}" log_success "All done!" } # Run main function main "$@" #!/usr/bin/env bash # # push-to-dockerhub.sh - Build and push Docker image to DockerHub # # This script builds a Docker image for ktransformers with standardized naming # and pushes it to DockerHub with both full and simplified tags. # # Features: # - Automatic version detection # - Standardized naming convention # - Multi-CPU variant support (AMX/AVX512/AVX2) # - Full and simplified tag support # - Retry logic for network failures # - Comprehensive error handling # # Usage: # ./push-to-dockerhub.sh [OPTIONS] # # Example: # ./push-to-dockerhub.sh \ # --cuda-version 12.8.1 \ # --repository kvcache/ktransformers \ # --also-push-simplified set -euo pipefail # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Source utility functions # shellcheck source=docker-utils.sh source "$SCRIPT_DIR/docker-utils.sh" ################################################################################ # Default Configuration ################################################################################ # Build parameters CUDA_VERSION="12.8.1" UBUNTU_MIRROR="0" HTTP_PROXY="" HTTPS_PROXY="" CPU_VARIANT="x86-intel-multi" FUNCTIONALITY="sft" # Paths DOCKERFILE="$SCRIPT_DIR/Dockerfile" CONTEXT_DIR="$SCRIPT_DIR" # Registry settings REGISTRY="docker.io" REPOSITORY="" # Must be provided by user # Options DRY_RUN=false SKIP_BUILD=false ALSO_PUSH_SIMPLIFIED=false MAX_RETRIES=3 RETRY_DELAY=5 EXTRA_BUILD_ARGS=() ################################################################################ # Help Message ################################################################################ usage() { cat <&2 log_info "Temporary tag: $temp_tag" >&2 # Prepare build arguments local build_args=() build_args+=("--build-arg" "CUDA_VERSION=$CUDA_VERSION") build_args+=("--build-arg" "UBUNTU_MIRROR=$UBUNTU_MIRROR") build_args+=("--build-arg" "CPU_VARIANT=$CPU_VARIANT") build_args+=("--build-arg" "BUILD_ALL_CPU_VARIANTS=1") # Add proxy settings if provided if [ -n "$HTTP_PROXY" ]; then build_args+=("--build-arg" "HTTP_PROXY=$HTTP_PROXY") fi if [ -n "$HTTPS_PROXY" ]; then build_args+=("--build-arg" "HTTPS_PROXY=$HTTPS_PROXY") fi # Add extra build args build_args+=("${EXTRA_BUILD_ARGS[@]}") # Add network host build_args+=("--network" "host") # Build command local build_cmd=( docker build -f "$DOCKERFILE" "${build_args[@]}" -t "$temp_tag" "$CONTEXT_DIR" ) # Display build command { log_info "Build command:" echo " ${build_cmd[*]}" } >&2 if [ "$DRY_RUN" = true ]; then log_warning "DRY RUN: Skipping actual build" >&2 return 0 fi # Execute build log_info "Starting Docker build (this may take 30-60 minutes)..." >&2 if "${build_cmd[@]}" >&2; then log_success "Docker image built successfully" >&2 echo "$temp_tag" else log_error "Docker build failed" >&2 exit 1 fi } ################################################################################ # Generate Tags ################################################################################ generate_tags() { local image_tag="$1" local timestamp="$2" if [ "$DRY_RUN" = true ]; then log_warning "DRY RUN: Using placeholder versions" # Use placeholder versions for dry run local versions="SGLANG_VERSION=0.5.6 KTRANSFORMERS_VERSION=0.4.3 LLAMAFACTORY_VERSION=0.9.3" else # Extract versions from image local versions versions=$(extract_versions_from_image "$image_tag") if [ $? -ne 0 ]; then log_error "Failed to extract versions from image" exit 1 fi # Validate versions if ! validate_versions "$versions"; then log_error "Version validation failed" exit 1 fi fi # Generate full tag local full_tag full_tag=$(generate_image_name "$versions" "$CUDA_VERSION" "$CPU_VARIANT" "$FUNCTIONALITY" "$timestamp") if [ -z "$full_tag" ]; then log_error "Failed to generate image name" exit 1 fi echo "FULL_TAG=$full_tag" # Generate simplified tag if requested if [ "$ALSO_PUSH_SIMPLIFIED" = true ]; then local ktrans_ver ktrans_ver=$(echo "$versions" | grep "^KTRANSFORMERS_VERSION=" | cut -d= -f2) local simplified_tag simplified_tag=$(generate_simplified_tag "$ktrans_ver" "$CUDA_VERSION") echo "SIMPLIFIED_TAG=$simplified_tag" fi } ################################################################################ # Push to Registry ################################################################################ push_image_with_retry() { local source_tag="$1" local target_tag="$2" local attempt=1 log_step "Pushing image: $target_tag" if [ "$DRY_RUN" = true ]; then log_warning "DRY RUN: Skipping actual push" log_info "Would execute:" echo " docker tag $source_tag $target_tag" echo " docker push $target_tag" return 0 fi # Tag the image log_info "Tagging image..." if ! docker tag "$source_tag" "$target_tag"; then log_error "Failed to tag image" return 1 fi # Push with retry logic while [ $attempt -le "$MAX_RETRIES" ]; do log_info "Push attempt $attempt/$MAX_RETRIES..." if docker push "$target_tag"; then log_success "Successfully pushed: $target_tag" return 0 else log_warning "Push failed (attempt $attempt/$MAX_RETRIES)" if [ $attempt -lt "$MAX_RETRIES" ]; then log_info "Retrying in ${RETRY_DELAY} seconds..." sleep "$RETRY_DELAY" fi ((attempt++)) fi done log_error "Failed to push after $MAX_RETRIES attempts" return 1 } ################################################################################ # Main ################################################################################ main() { log_step "KTransformers Docker Image Build and Push" # Parse arguments parse_args "$@" # Validate configuration validate_config # Generate timestamp TIMESTAMP=$(get_beijing_timestamp) log_info "Build timestamp: $TIMESTAMP" # Display configuration display_summary "Push Configuration" \ "CUDA Version: $CUDA_VERSION" \ "Ubuntu Mirror: $UBUNTU_MIRROR" \ "CPU Variant: $CPU_VARIANT" \ "Functionality: $FUNCTIONALITY" \ "Registry: $REGISTRY" \ "Repository: $REPOSITORY" \ "Push Simplified: $ALSO_PUSH_SIMPLIFIED" \ "Skip Build: $SKIP_BUILD" \ "HTTP Proxy: ${HTTP_PROXY:-}" \ "HTTPS Proxy: ${HTTPS_PROXY:-}" \ "Dockerfile: $DOCKERFILE" \ "Context Dir: $CONTEXT_DIR" \ "Timestamp: $TIMESTAMP" \ "Dry Run: $DRY_RUN" # Build image TEMP_TAG=$(build_image) if [ "$DRY_RUN" = true ]; then TEMP_TAG="ktransformers:temp-dryrun" fi # Generate tags log_step "Generating tags" TAG_INFO=$(generate_tags "$TEMP_TAG" "$TIMESTAMP") # Parse tag info FULL_TAG=$(echo "$TAG_INFO" | grep "^FULL_TAG=" | cut -d= -f2) SIMPLIFIED_TAG=$(echo "$TAG_INFO" | grep "^SIMPLIFIED_TAG=" | cut -d= -f2 || echo "") log_info "Full tag: $FULL_TAG" if [ -n "$SIMPLIFIED_TAG" ]; then log_info "Simplified tag: $SIMPLIFIED_TAG" fi # Push full tag FULL_IMAGE="$REGISTRY/$REPOSITORY:$FULL_TAG" if ! push_image_with_retry "$TEMP_TAG" "$FULL_IMAGE"; then log_error "Failed to push full tag" exit 1 fi # Push simplified tag if requested if [ -n "$SIMPLIFIED_TAG" ]; then SIMPLIFIED_IMAGE="$REGISTRY/$REPOSITORY:$SIMPLIFIED_TAG" if ! push_image_with_retry "$TEMP_TAG" "$SIMPLIFIED_IMAGE"; then log_warning "Failed to push simplified tag, but continuing..." fi fi # Cleanup temporary image if [ "$DRY_RUN" = false ]; then log_step "Cleaning up temporary image" cleanup_temp_images "$TEMP_TAG" fi # Display summary local summary_lines=( "Successfully pushed images:" "" "Full tag:" " $FULL_IMAGE" "" ) if [ -n "$SIMPLIFIED_TAG" ]; then summary_lines+=( "Simplified tag:" " $SIMPLIFIED_IMAGE" "" ) fi summary_lines+=( "To pull the image:" " docker pull $FULL_IMAGE" "" "To run the container:" " docker run -it --rm $FULL_IMAGE /bin/bash" ) display_summary "Push Complete" "${summary_lines[@]}" log_success "All done!" } # Run main function main "$@"