40a8dc2297
try: add entrypoint and env-file options, fix genric options TODO: bind mount the source into the build directly (see dockerfile buildkit) added example folder with examples refactored: install script much more robust, allows custom target removedj volume command from dockerfile
293 lines
No EOL
7.3 KiB
Bash
Executable file
293 lines
No EOL
7.3 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
docker_image_build () {
|
|
|
|
local targets=(dev arm amd deploy private multi)
|
|
local verbose; local BUILD_SRC; local log_dir; local no_prompt
|
|
declare OPTION; declare OPTARG; declare OPTIND
|
|
|
|
BDIR=$(dirname "$(realpath "$BASH_SOURCE")")
|
|
export BDIR
|
|
# load script library
|
|
source $BDIR/lib/load.sh
|
|
|
|
# check for subcommands first
|
|
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}
|
|
}
|
|
|
|
|
|
[[ -z "$PS1" ]] || no_prompt=true
|
|
overwrite=true
|
|
target=dev
|
|
|
|
while getopts 'g:e:b:d:t:ncr:u:plhs:w:akvoi' OPTION; do
|
|
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
|
|
case "$OPTION" in
|
|
e)
|
|
local efile
|
|
echo $PWD
|
|
[[ $(isAbsPath $OPTARG) ]] && efile=$OPTARG || efile=$(realpath $OPTARG)
|
|
if source "$efile"; then
|
|
echo "********************"
|
|
echo loaded build environment file at
|
|
echo $efile
|
|
echo "----------"
|
|
cat $efile
|
|
echo "*********************"
|
|
else
|
|
echo unable to source $efile, exiting && return 2
|
|
return 2
|
|
fi
|
|
;;
|
|
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)
|
|
# building source from which to bind into build, default is src/ in current directory
|
|
BUILD_SRC=$OPTARG
|
|
;;
|
|
d)
|
|
# LINUX_DISTRO=$OPTARG
|
|
LINUX_DISTRO=$OPTARG
|
|
;;
|
|
l)
|
|
# append distro name to image name
|
|
append_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))
|
|
|
|
BUILD_SRC=${BUILD_SRC:-${PWD}/src}
|
|
|
|
if [[ ! $(isAbsPath $BUILD_SRC) ]] ; then
|
|
if [[ ${BUILD_SRC} == "_base_" ]]; then
|
|
BUILD_SRC=${BDIR}/src
|
|
else
|
|
BUILD_SRC=$(realpath ${BUILD_SRC})
|
|
fi
|
|
fi
|
|
|
|
log_dir=$PWD/logs
|
|
mkdir -p $log_dir
|
|
|
|
if [[ ! -d $BUILD_SRC ]]; then
|
|
|
|
if $no_prompt ; then
|
|
echo -e "\e[1;31mWARNING: no build source directory at $BUILD_SRC was not found"
|
|
echo aborting...
|
|
echo -e "\e[1;31mNOTE: use '_base_' to explicitly use the in uci-docker-build repo\e[1;37m"
|
|
return 3
|
|
else
|
|
echo -e "\e[1;31mWARNING: build scripts source directory at $BUILD_SRC does not exist.\e[1;37m"
|
|
echo "Do you want to use the uci-docker-build repo source scripts"
|
|
echo "at $BDIR/src "
|
|
read -n 1 -p "instead? [y]=>" REPLY
|
|
[[ $REPLY != "y" ]] && echo -e "\n" && return 0
|
|
BUILD_SRC=$BDIR/src
|
|
echo -e "\n\e[1;31mNOTE: use '_base_' to explicitly use the in uci-docker-build repo\e[1;37m"
|
|
fi
|
|
|
|
fi
|
|
|
|
pushd $BDIR || return 3
|
|
|
|
[[ ! "${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=${NAME:-$1}
|
|
RUSER=${2:-$RUSER}
|
|
if [[ $NAME ]]; then
|
|
[[ $add_distro ]] && NAME=$NAME-${LINUX_DISTRO}
|
|
else
|
|
NAME=${LINUX_DISTRO}
|
|
fi
|
|
IMAGE_NAME=$([[ $RUSER ]] && echo ${RUSER}/)${NAME}
|
|
# 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
|
|
|
|
|
|
echo -e "\n******************************************"
|
|
echo "Using scripts source directory at $BUILD_SRC"
|
|
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 $BUILD_SRC to be copied to ${BUILD_DIR:-/build} in container ***** "
|
|
ls -la $BUILD_SRC
|
|
echo -e "\n----- base init script init.sh ------"
|
|
cat $BUILD_SRC/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 ${BUILD_SRC:-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 $@ |