#!/bin/bash docker_image_build () { local targets=(dev arm amd deploy private multi) local verbose; local scripts_dir; local log_dir; declare OPTION; declare OPTARG; declare OPTIND SDIR=$(pwd) BDIR=$(dirname "$(realpath "$BASH_SOURCE")") export SDIR export BDIR pushd $BDIR > /dev/null source $BDIR/lib/load.sh case "$1" in try) shift 1 popd > /dev/null || return 2 try_container "$@" return $? ;; image_name) shift 1 image_name "$@" return $? ;; tag) shift 1 image_tag "$@" return $? ;; push) shift 1 image_push "$@" return $? ;; info) shift 1 [[ $1 == "arch" ]] && { shift 1; image_arch "$@"; return $?; } [[ $1 == "exists" ]] && { shift 1; image_exists "$@"; return $?; } [[ $1 == "id" ]] && { shift 1; image_id "$@"; return $?; } image_info "$@"; return $? ;; esac exit_abnormal() { # Function: Exit with error. usage return ${1:-1} } scripts_dir=$SDIR/src # TODO allow log directory option log_dir=$SDIR/logs mkdir -p $log_dir [[ -z "$PS1" ]] || no_prompt=true overwrite=true target=dev while getopts 'g:e:b:d:t:ncr:u:pxhs:w:akvoi' OPTION; do # echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND} case "$OPTION" in e) local efile=$SDIR/$OPTARG if [[ -f $efile ]]; then source "$efile" [[ ! $? -eq 0 ]] && echo source of $efile failed, exiting && return 2 else echo no environment file at $efile, exiting return 2 fi echo "----------" echo loaded environment filen $efile cat $efile echo "----------" ;; o) unset overwrite ;; v) verbose=true ;; a) # automated - script is to be run without prompt (non-interactive) no_prompt=true ;; k) # keep the build scripts in the image, by default they are removed KEEP=true ;; w) # the work directory to put the build scripts in container (default is /opt/build) BUILD_DIR=$OPTARG ;; b) # CUSTOM BASE IMAGE BASE_IMAGE=$OPTARG ;; s) # scripts subdirectory from which to bind to scripts/, default is src/ if isAbsPath $OPTARG; then scripts_dir=$OPTARG elif [ "$OPTARG" == "_base_" ]; then scripts_dir=$BDIR/src else scripts_dir=$SDIR/$OPTARG fi ;; d) # LINUX_DISTRO=$OPTARG LINUX_DISTRO=$OPTARG ;; x) # Exclude distro from image name exclude_distro=true ;; t) target=$OPTARG ;; g) TAG=$OPTARG ;; u) RUSER=$OPTARG ;; c) try=true ;; p) push=true ;; n) nocache="--no-cache" ;; r) REPO=$OPTARG ;; h) exit_abnormal 0 return 0 ;; *) echo "unknown $0 option -$OPTARG" exit_abnormal 4 ;; esac done shift $((OPTIND - 1)) if [[ ! -d $scripts_dir ]]; then if [[ ! $no_prompt ]]; then echo -e "\e[1;31mWARNING: build scripts directory$scripts_dir does not exist.\e[1;37m" echo "Do you want to use the base scripts" read -n 1 -p "directory at $BDIR/src? to continue [y]=>" REPLY [[ $REPLY != "y" ]] && echo -e "\n" && return 0 echo fi echo -e "\e[1;31mscripts directory $scripts_dir was not found using base build scripts at $BDIR/src\e[1;37m" scripts_dir=$BDIR/src fi [[ ! "${targets[@]}" =~ $target ]] && echo $target is not a valid target && echo valid targets are: ${targets[@]} && exit 4 LINUX_DISTRO=${LINUX_DISTRO:-alpine} if [[ $BASE_IMAGE ]]; then echo determining DISTRO of base image: $BASE_IMAGE LINUX_DISTRO=$(get_distro -d $BASE_IMAGE) [[ ! $LINUX_DISTRO ]] && echo "unable to get base image OS for: $BASE_IMAGE, aborting build" && exit 1 echo $BASE_IMAGE is built from distro $LINUX_DISTRO else BASE_IMAGE=$LINUX_DISTRO fi name=$1 RUSER=${2:-$RUSER} IMAGE_NAME=$([[ $RUSER ]] && echo ${RUSER}/)${name}$([[ ! $exclude_distro ]] && echo -${LINUX_DISTRO}) # TODO writing to existing tag untags existing image so write a new tag to that image then continue # retag existing image and remove former tag if [[ $(image_exists $IMAGE_NAME) ]]; then if [[ $overwrite ]]; then image_delete $IMAGE_NAME else newtag=$(date +'%d%H%M%S') echo image exists retaging $(image_name $IMAGE_NAME) with tag :$newtag image_tag $IMAGE_NAME $IMAGE_NAME:$newtag image_tag -r $IMAGE_NAME fi fi # BASE_IMAGE=$([[ $BASE_IMAGE == *:* ]] && echo $BASE_IMAGE || echo $BASE_IMAGE:latest) #$([[ ! $BASE_IMAGE == *:* ]] && echo :latest) export BASE_IMAGE export TAG export IMAGE_NAME export LINUX_DISTRO export BUILD_DIR export KEEP export SYSADMIN_PW export BUST_INIT_CACHE echo "******************************************" echo "Building with base image: $BASE_IMAGE" echo "Outputing to image name => $IMAGE_NAME<-arch>:${TAG:-latest}" echo "Linux Distro: $LINUX_DISTRO" echo "Using build target: $target" echo "Build Command: docker buildx --builder ${builder} bake ${nocache} ${target}" if [[ $verbose ]]; then echo -e "\n---------------------------------" docker buildx bake --print $target echo -e "\n---------------------------------" echo "build scripts at $scripts_dir to be copied to ${BUILD_DIR:-/build} in container ***** " ls -la $scripts_dir echo -e "\n----- base init script init.sh ------" cat $scripts_dir/init.sh echo -e "\n---------------------------------" fi echo -e "\n***************************************" if [[ ! $no_prompt ]]; then read -n 1 -p "do you want to continue [y]=>" REPLY [[ $REPLY != "y" ]] && echo -e "\n" && exit 0 fi builder=default if [ $target == "deploy" ]; then builder=deploy if ! docker buildx ls | grep -q deploy ; then echo multiarch deploy builder does not exist, creating with docker-container driver docker buildx create --name deploy --driver docker-container >/dev/null docker buildx ls | grep deploy fi fi [[ $target == "private" && ! $REPO ]] && echo "must use '-r ' if building to private repo" && exit 3 # copy source directory to temporary .src/ subdirectory # MUST either be readable by all or group readable by docker group rm -rf $BDIR/.src rsync -aAru ${scripts_dir:-src}/ $BDIR/.src ls -la $BDIR/.src docker buildx --builder ${builder} bake ${nocache} ${target} 2>&1 | tee "$log_dir/${IMAGE_NAME//\//-}build.log" [[ $? == 0 ]] && echo succcess building image $IMAGE_NAME || exit_abnormal 1 rm -rf $BDIR/.src # if [[ $target == "private" ]]; then # ./push -a -r $REPO $IMAGE_NAME # ./push -r $REPO $IMAGE_NAME # else # if [[ $push && (! $target == "dev") ]];then # echo pushing now # ./push $([[ $target == "arm" ]] && echo -a) -r $REPO $IMAGE_NAME # fi # fi popd > /dev/null if [[ ($try || $target == "dev") ]] && [[ ! $no_prompt ]]; then echo trying newly built image in a container try_container -m opt $([[ $target == "deploy" ]] && echo -p) $IMAGE_NAME fi #echo reset to calling directory $PWD } # if script was executed then call the function (return 0 2>/dev/null) || docker_image_build $@