uci-docker-build/build
David Kebler b88ea929b0 minor refactoring of bind script
* fix image name generation
   * add logging directory and direct output to files there
removed linked mount in try script as btrfs does not create volume directories (bind mount only now)
move packages and init into separate directories to keep cache separate
fix some minor bugs
2023-03-22 09:10:54 -07:00

275 lines
No EOL
6.9 KiB
Bash
Executable file

#!/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 <private repo>' 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 $@