From 40a8dc2297ba6d3ed4e6340c3891ae09e11f6bbc Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sat, 25 Mar 2023 11:27:22 -0700 Subject: [PATCH] refactor: new BUIlD_SRC supported from multiple locations including environment 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 --- .dockerignore | 1 + Dockerfile | 10 +++- build | 114 +++++++++++++++++++++---------------- examples/aliases | 13 +++++ examples/example-build.env | 9 +++ examples/example.build | 1 + install | 28 ++++++++- lib/src/try | 21 ++++--- 8 files changed, 136 insertions(+), 61 deletions(-) create mode 100644 .dockerignore create mode 100755 examples/aliases create mode 100644 examples/example-build.env create mode 100644 examples/example.build diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..29b5b77 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +archive/* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7f10f8e..7566710 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ +# syntax=docker/dockerfile:latest ARG BASE_IMAGE FROM $BASE_IMAGE +ARG PENV ARG BASE_IMAGE ARG KEEP ARG SYSADMIN_PW @@ -31,7 +33,9 @@ RUN echo -e "\n ************************************************* \n" \ echo -e "\n ************* End Initialzation ************************" # END INITIALIZATION -VOLUME [ "/data", "/opt", "/shell, /home/sysadmin" ] -WORKDIR /opt -# ENTRYPOINT ["entrypoint.sh"] +# default command CMD ["/bin/bash", "-l"] +# default +WORKDIR /opt + + diff --git a/build b/build index 6b1ece6..8934027 100755 --- a/build +++ b/build @@ -3,17 +3,15 @@ docker_image_build () { local targets=(dev arm amd deploy private multi) -local verbose; local scripts_dir; local log_dir; +local verbose; local BUILD_SRC; local log_dir; local no_prompt declare OPTION; declare OPTARG; declare OPTIND -SDIR=$(pwd) BDIR=$(dirname "$(realpath "$BASH_SOURCE")") -export SDIR export BDIR -pushd $BDIR > /dev/null - +# load script library source $BDIR/lib/load.sh +# check for subcommands first case "$1" in try) shift 1 @@ -50,30 +48,29 @@ exit_abnormal() { # Function: Exit with error. 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 +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=$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 + 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 - echo "----------" - echo loaded environment filen $efile - cat $efile - echo "----------" ;; o) unset overwrite @@ -98,22 +95,16 @@ while getopts 'g:e:b:d:t:ncr:u:pxhs:w:akvoi' OPTION; do 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 + # building source from which to bind into build, default is src/ in current directory + BUILD_SRC=$OPTARG ;; d) # LINUX_DISTRO=$OPTARG LINUX_DISTRO=$OPTARG ;; - x) - # Exclude distro from image name - exclude_distro=true + l) + # append distro name to image name + append_distro=true ;; t) target=$OPTARG @@ -149,18 +140,40 @@ 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 +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 - echo + 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 - 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 +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} @@ -174,10 +187,14 @@ LINUX_DISTRO=$(get_distro -d $BASE_IMAGE) BASE_IMAGE=$LINUX_DISTRO fi -name=$1 +NAME=${NAME:-$1} RUSER=${2:-$RUSER} - -IMAGE_NAME=$([[ $RUSER ]] && echo ${RUSER}/)${name}$([[ ! $exclude_distro ]] && echo -${LINUX_DISTRO}) +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 @@ -202,9 +219,10 @@ export LINUX_DISTRO export BUILD_DIR export KEEP export SYSADMIN_PW -export BUST_INIT_CACHE -echo "******************************************" + +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" @@ -214,10 +232,10 @@ 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 "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 $scripts_dir/init.sh + cat $BUILD_SRC/init.sh echo -e "\n---------------------------------" fi echo -e "\n***************************************" @@ -242,7 +260,7 @@ fi # 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 +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" diff --git a/examples/aliases b/examples/aliases new file mode 100755 index 0000000..770cfdc --- /dev/null +++ b/examples/aliases @@ -0,0 +1,13 @@ +#!/bin/bash +# three ways to invoke with --no-cache + +# inline +# NO_CACHE=true ./build "$@" + +# with -n option (prefered) +./build -n "$@" +alias rebuild="build -nfunction_list" + +# as export +#export NO_CACHE=true +#./build "$@" diff --git a/examples/example-build.env b/examples/example-build.env new file mode 100644 index 0000000..45be2c9 --- /dev/null +++ b/examples/example-build.env @@ -0,0 +1,9 @@ +# do not set LINUX_DISTRO if setting base image, it will be ignorned +LINUX_DISTRO=alpine +# BASE_IMAGE="dockerhubuser/mybase" +TAG=1.0.0 +RUSER=dockerhubuser +REPO=my.priviate.repo.net + + + diff --git a/examples/example.build b/examples/example.build new file mode 100644 index 0000000..5e1f1f0 --- /dev/null +++ b/examples/example.build @@ -0,0 +1 @@ +dbuild -e example-build.env "$@" diff --git a/install b/install index 7ef0890..cd96516 100755 --- a/install +++ b/install @@ -1,3 +1,27 @@ #!/bin/bash -ln -nsf $(dirname "$(realpath "$BASH_SOURCE")")/build /opt/bin/dbuild -dbuild -h \ No newline at end of file +builder=$(dirname "$(realpath "$BASH_SOURCE")") +target=$1 +[[ $# -eq 2 ]] && target=$1/$2 +target=${target:-/opt/bin/dbuild} +cmd=$(basename $target) +parent=$(dirname $target) +echo NOTE: the uci build script can be called directly at $builder +# echo "$PATH --- $parent" +declare -a a="(${PATH//:/ })" +for i in ${a[*]}; do [[ $i == $parent ]] && found=true; done +if [[ $found ]]; then + echo creating a link \'$cmd\' in \'$parent\' to \'$builder\' + if ln -ns $builder/build ${1:-/opt/bin/dbuild}; then + [[ ! $(command -v $cmd) ]] && echo FATAL: link failed $cmd not found in path \ + || echo install success: try \'$cmd -h\' now + else + echo Error creating link + echo if \': Permission denied\' 'then' run \'sudo ./install\' + fi + else + echo $parent not in current path + echo $PATH + echo link to script not created + echo Alternatively export an environment variable with $builder + echo and use that to invoke the script + fi \ No newline at end of file diff --git a/lib/src/try b/lib/src/try index 974d46e..91c75e7 100755 --- a/lib/src/try +++ b/lib/src/try @@ -10,15 +10,21 @@ try_container () { declare -A arch=( ["x86_64"]="" ["aarch64"]="-arm64") local mp;local cuser; local hmp; local bind; local vname; local prod; local priv - local dkpath; local hostmp; local evar; local hostmap; local cleanup + local dkpath; local hostmp; local evar; local hostmap; local cleanup; local efile - [[ $# -lt 1 ]] && echo "image name required to try" && return 1 + [[ $# -lt 1 ]] && echo "image name required to try" && return 1 declare OPTION; declare OPTARG; declare OPTIND OPTIND=0 - while getopts 'o:dpr:t:u:m:h:ke:' OPTION; do + while getopts 'f:o:dpr:t:u:m:h:ke:s:' OPTION; do # echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND} case "$OPTION" in + s) + entrypoint="--entrypoint $OPTARG" + ;; + f) + efile"--env-file $OPTARG" + ;; d) dryrun="echo " ;; @@ -35,7 +41,7 @@ try_container () { mp=$OPTARG ;; o) - options="$option $OPTARG" + options=$OPTARG ;; h) hmp=$OPTARG @@ -83,9 +89,7 @@ try_container () { docker rm try-$name > /dev/null 2>&1 if [[ $mp ]]; then hostmp="${hmp:-${PWD}/mnt/$mp}" - if [[ ! $(isAbsPath $hostmp) ]]; then - [[ $SDIR ]] && hostmp=$SDIR/$hostmp || hostmp=$PWD/$hostmp - fi + [[ ! $(isAbsPath $hostmp) ]] && hostmp=$PWD/$hostmp vname="try-$name${dir//\//-}" mkdir -p "$hostmp" # echo bind $dir to volume $vname @@ -109,6 +113,7 @@ try_container () { # --entrypoint /opt/scripts/entrypoint.sh \ $dryrun docker run -i -t --rm $priv $evar $hostmap $options \ + ${entrypoint} ${efile} \ $([[ $cuser ]] && echo "--user $cuser") \ --name try-$name --hostname try-$host-$name \ $([[ $mp ]] && echo "-v $vname:/$mp") \ @@ -134,4 +139,4 @@ try_container () { } # if script was executed then call the function -(return 0 2>/dev/null) || try_container $@ \ No newline at end of file +(return 0 2>/dev/null) || try_container "$@" \ No newline at end of file