blob: 44a5439c54c132cccfaa0a21d3fbe80af3337443 [file] [log] [blame]
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#
# AINode Docker Image Build Script
# Run this script from docker/src/main directory
# Usage: ./build.sh -v <version> [options]
#
set -e
# Get script directory (should be docker/src/main)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Project root is 3 levels up from docker/src/main
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
# Default configuration
VERSION=""
IMAGE_NAME="apache/iotdb"
IMAGE_TAG_SUFFIX="ainode"
PUSH_IMAGE=false
NO_CACHE=false
DATA_DIR="/data/ainode"
REGISTRY_PREFIX=""
# Usage information
usage() {
cat << EOF
Usage: $0 -v <version> [options]
Required:
-v, --version <version> Specify IoTDB version (e.g., 2.0.8)
Options:
-p, --push Push image to registry after build
-n, --no-cache Build without Docker cache
-t, --tag <tag> Custom image tag (default: <version>-ainode)
-d, --data-dir <path> Data directory path (default: /data/ainode)
-r, --registry <url> Registry prefix (e.g., registry.example.com)
-h, --help Show this help message
Examples:
# Build version 2.0.8
$0 -v 2.0.8
# Build and push
$0 -v 2.0.8 --push
# Build with custom data directory
$0 -v 2.0.8 --data-dir /mnt/data/ainode
EOF
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-v|--version)
VERSION="$2"
shift 2
;;
-p|--push)
PUSH_IMAGE=true
shift
;;
-n|--no-cache)
NO_CACHE=true
shift
;;
-t|--tag)
CUSTOM_TAG="$2"
shift 2
;;
-d|--data-dir)
DATA_DIR="$2"
shift 2
;;
-r|--registry)
REGISTRY_PREFIX="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1"
usage
exit 1
;;
esac
done
# Validate version
if [ -z "$VERSION" ]; then
echo "Error: Version is required. Use -v <version> to specify."
usage
exit 1
fi
# Check if distribution package exists (relative to project root)
DIST_FILE="${PROJECT_ROOT}/distribution/target/apache-iotdb-${VERSION}-ainode-bin.zip"
if [ ! -f "$DIST_FILE" ]; then
echo "Error: Distribution file not found: $DIST_FILE"
echo "Please build the project first: mvn clean package -DskipTests"
exit 1
fi
# Check if data directory exists
if [ ! -d "$DATA_DIR" ]; then
echo "Warning: Data directory does not exist: $DATA_DIR"
echo "Creating empty directory..."
mkdir -p "$DATA_DIR"
fi
# Determine image tag
if [ -n "$CUSTOM_TAG" ]; then
IMAGE_TAG="${CUSTOM_TAG}"
else
IMAGE_TAG="${VERSION}-${IMAGE_TAG_SUFFIX}"
fi
# Construct full image name
if [ -n "$REGISTRY_PREFIX" ]; then
FULL_IMAGE_NAME="${REGISTRY_PREFIX}/${IMAGE_NAME}:${IMAGE_TAG}"
else
FULL_IMAGE_NAME="${IMAGE_NAME}:${IMAGE_TAG}"
fi
echo "============================================"
echo "Building AINode Docker Image"
echo "============================================"
echo "Version: ${VERSION}"
echo "Distribution: ${DIST_FILE}"
echo "Data Directory: ${DATA_DIR}"
echo "Dockerfile: ${SCRIPT_DIR}/Dockerfile-2.0.x-ainode"
echo "Image Name: ${FULL_IMAGE_NAME}"
echo "Build Context: ${PROJECT_ROOT}"
echo "Script Dir: ${SCRIPT_DIR}"
echo "============================================"
# Prepare data directory for Docker build context
# Use a unique name to avoid .dockerignore conflicts with common patterns like 'tmp*'
BUILD_DATA_DIR_NAME="ainode-build-data"
TMP_DATA_DIR="${SCRIPT_DIR}/${BUILD_DATA_DIR_NAME}"
echo "Preparing data directory for build context at: ${TMP_DATA_DIR}"
# Clean up old data if exists
if [ -d "$TMP_DATA_DIR" ]; then
echo "Cleaning up existing build data directory..."
rm -rf "$TMP_DATA_DIR"
fi
# Create directory and copy data
mkdir -p "$TMP_DATA_DIR"
if [ -d "$DATA_DIR" ] && [ "$(ls -A $DATA_DIR 2>/dev/null)" ]; then
echo "Copying data from ${DATA_DIR} to ${TMP_DATA_DIR}..."
cp -r "$DATA_DIR"/* "$TMP_DATA_DIR/"
echo "Copied $(ls -1 "$TMP_DATA_DIR" | wc -l) items"
else
echo "No data to copy, created empty directory"
fi
# Verify the directory exists and show contents
if [ ! -d "$TMP_DATA_DIR" ]; then
echo "Error: Failed to create temporary data directory: ${TMP_DATA_DIR}"
exit 1
fi
echo "Build data directory contents:"
ls -la "$TMP_DATA_DIR" || echo "(empty directory)"
# Check if .dockerignore exists and might exclude our directory
DOCKERIGNORE_FILE="${PROJECT_ROOT}/.dockerignore"
if [ -f "$DOCKERIGNORE_FILE" ]; then
if grep -q "ainode-build-data" "$DOCKERIGNORE_FILE" || grep -qE "^\*|^tmp|^data" "$DOCKERIGNORE_FILE"; then
echo ""
echo "WARNING: .dockerignore file detected at ${DOCKERIGNORE_FILE}"
echo "It may exclude the '${BUILD_DATA_DIR_NAME}' directory from build context."
echo "If build fails with 'COPY failed', add exception to .dockerignore:"
echo " !docker/src/main/${BUILD_DATA_DIR_NAME}/"
echo ""
fi
fi
# Cleanup function
cleanup() {
echo "Cleaning up temporary data directory: ${TMP_DATA_DIR}"
rm -rf "$TMP_DATA_DIR"
}
trap cleanup EXIT
# Verify Dockerfile exists
DOCKERFILE="${SCRIPT_DIR}/Dockerfile-2.0.x-ainode"
if [ ! -f "$DOCKERFILE" ]; then
echo "Error: Dockerfile not found at: ${DOCKERFILE}"
exit 1
fi
# Build Docker image
# Build context is PROJECT_ROOT (3 levels up from current script)
BUILD_CMD="docker build"
BUILD_CMD+=" --file ${DOCKERFILE}"
BUILD_CMD+=" --build-arg VERSION=${VERSION}"
BUILD_CMD+=" --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
BUILD_CMD+=" --build-arg VCS_REF=$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
if [ "$NO_CACHE" = true ]; then
BUILD_CMD+=" --no-cache"
fi
BUILD_CMD+=" --tag ${FULL_IMAGE_NAME}"
BUILD_CMD+=" ${PROJECT_ROOT}"
echo ""
echo "Executing Docker build..."
echo "Command: ${BUILD_CMD}"
echo ""
${BUILD_CMD} || {
echo ""
echo "Error: Docker build failed"
echo ""
echo "Troubleshooting tips:"
echo "1. If error is 'COPY failed: no such file or directory', check if .dockerignore excludes 'docker/src/main/${BUILD_DATA_DIR_NAME}/'"
echo "2. Ensure Docker daemon is running"
echo "3. Try running with --no-cache option"
exit 1
}
echo ""
echo "Build completed successfully: ${FULL_IMAGE_NAME}"
# Push image if requested
if [ "$PUSH_IMAGE" = true ]; then
echo "Pushing image to registry..."
docker push "${FULL_IMAGE_NAME}"
# Also push latest tag for release versions
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
LATEST_TAG="latest-${IMAGE_TAG_SUFFIX}"
if [ -n "$REGISTRY_PREFIX" ]; then
LATEST_NAME="${REGISTRY_PREFIX}/${IMAGE_NAME}:${LATEST_TAG}"
else
LATEST_NAME="${IMAGE_NAME}:${LATEST_TAG}"
fi
echo "Tagging and pushing: ${LATEST_NAME}"
docker tag "${FULL_IMAGE_NAME}" "${LATEST_NAME}"
docker push "${LATEST_NAME}"
fi
fi
echo ""
echo "Done!"