#!/bin/bash declare targets=(dev arm amd deploy private multi) declare OPTION; declare OPTARG; declare OPTIND SDIR=$(pwd) BDIR=$(dirname "$(realpath "$0")") pushd $BDIR > /dev/null if [ $1 == "try" ]; then ./try $2 $SDIR exit fi usage() { # Function: Print a help message. echo "Image Build Script: Creates one or more images using a target in the docker-bake.hcl file" echo "USAGE: $0 buildtarget " echo "valid targets: ${targets[*]}; default: dev" echo no argument options: echo "-c try out the image by starting a container terminal therein, for dev target this is the default;" echo "-x exclude distro from image name;" echo "-n for --no_cache" echo "-p push to repository; after build push to repository default is hub.docker.common (not need for deploy target)" echo required argument options: echo "-d supported: alpine, debian, ubuntu, default: alpine; if base image set distro will be determined" echo "-t tag following : in output image name (i.e. REPO/USER/NAME:TAG), default: latest" echo "-u ; repository user prefix in output image name (i.e. REPO/USER/NAME:TAG)" echo "-r ; private repo name, do not use for hub.docker.com (docker.io)" echo "-b ; used in FROM in Dockerfile, default is official distro image (e.g. alpine:latest)" echo "-w ; set a custom WORKDIR in Dockerfile, default is /opt/build" } exit_abnormal() { # Function: Exit with error. usage exit ${1:-1} } source $BDIR/helpers.lib scripts_dir=$SDIR/src while getopts ':b:d:t:ncr:u:pxhs:w:ak' OPTION; do # echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND} case "$OPTION" in 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) SCRIPTS=$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) TAG=$OPTARG ;; u) RUSER=$OPTARG ;; c) try=true ;; p) push=true ;; n) nocache="--no-cache" ;; r) REPO=$OPTARG ;; h) exit_abnormal 0 ;; *) echo "unknown $0 option -$OPTARG" exit_abnormal 4 ;; esac done shift $((OPTIND - 1)) target=${1:-dev} LINUX_DISTRO=${LINUX_DISTRO:-alpine} name=$2 RUSER=${3:-$RUSER} IMAGE_NAME=$([[ $RUSER ]] && echo ${RUSER}/)${name}$([[ (! $exclude_distro) && $name ]] && echo "-")$([[ ! $exclude_distro ]] && echo ${LINUX_DISTRO}) 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 else BASE_IMAGE=$LINUX_DISTRO 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 SCRIPTS export KEEP echo " ******************************************" echo "Building with base image: $BASE_IMAGE, output image name => $IMAGE_NAME" echo "Linux Distro: $LINUX_DISTRO" echo "Using build target: $target" docker buildx bake --print $target echo -e "\n---------------------------------" echo "build scripts at $scripts_dir to be copied to ${SCRIPTS:-/opt/build} in container ***** " ls -la $scripts_dir echo -e "\n----- base init script init.sh ------" cat $scripts_dir/init.sh echo -e "\n---------------------------------" 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 [[ ! "${targets[@]}" =~ $target ]] && echo $target is not a valid target && echo valid targets are: ${targets[@]} && exit 4 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 # mount source directory to temporary .src/ subdirectory fusermount -u .src > /dev/null 2>&1 mkdir .src bindfs ${scripts_dir:-src} .src docker buildx --builder ${builder} bake ${nocache} ${target} 2>&1 | tee build.log fusermount -u .src > /dev/null 2>&1 rm -rf .src/ [[ $? == 0 ]] && echo succcess building image $IMAGE_NAME || exit_abnormal 1 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 [[ ($try || $target == "dev") ]] && ./try $([[ $target == "deploy" ]] && echo -p) $IMAGE_NAME popd > /dev/null #echo reset to calling directory $PWD