convert scripts to functions and create library of secondary functions. Enable calling those directly form build script/function

more image scripts to /src folder
master
Kebler Network System Administrator 2023-01-17 15:20:30 -08:00
parent 4f3b4b94fe
commit dfc0ecf966
34 changed files with 804 additions and 180 deletions

View File

@ -6,6 +6,7 @@
# with -n option (prefered) # with -n option (prefered)
./build -n "$@" ./build -n "$@"
alias rebuild="build -nfunction_list"
# as export # as export
#export NO_CACHE=true #export NO_CACHE=true

101
build
View File

@ -1,46 +1,54 @@
#!/bin/bash #!/bin/bash
declare targets=(dev arm amd deploy private multi)
docker_image_build () {
local targets=(dev arm amd deploy private multi)
local verbose
declare OPTION; declare OPTARG; declare OPTIND declare OPTION; declare OPTARG; declare OPTIND
SDIR=$(pwd) SDIR=$(pwd)
BDIR=$(dirname "$(realpath "$0")") BDIR=$(dirname "$(realpath "$BASH_SOURCE")")
pushd $BDIR > /dev/null pushd $BDIR > /dev/null
if [ $1 == "try" ]; then source $BDIR/lib/load.sh
./try $2 $SDIR
exit
fi
usage() { # Function: Print a help message. case "$1" in
echo "Image Build Script: Creates one or more images using a target in the docker-bake.hcl file" try)
echo "USAGE: $0 <setup options> buildtarget <imagename, imageuser>" shift 1
echo "valid targets: ${targets[*]}; default: dev" try_container "$@"
echo no argument options: return $?
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;" tag)
echo "-n for --no_cache" shift 1
echo "-p push to repository; after build push to repository default is hub.docker.common (not need for deploy target)" image_tag "$@"
echo required argument options: return $?
echo "-d <LINUX_DISTRO> supported: alpine, debian, ubuntu, default: alpine; if base image set distro will be determined" ;;
echo "-t <TAG> tag following : in output image name (i.e. REPO/USER/NAME:TAG), default: latest" info)
echo "-u <USER>; repository user prefix in output image name (i.e. REPO/USER/NAME:TAG)" shift 1
echo "-r <REPO>; private repo name, do not use for hub.docker.com (docker.io)" [[ $1 == "arch" ]] && { shift 1; image_arch "$@"; return $?; }
echo "-b <BASE_IMAGE>; used in FROM in Dockerfile, default is official distro image (e.g. alpine:latest)" [[ $1 == "exists" ]] && { shift 1; image_exists "$@"; return $?; }
echo "-w <SCRIPTS>; set a custom WORKDIR in Dockerfile, default is /opt/build" [[ $1 == "id" ]] && { shift 1; image_id "$@"; return $?; }
} image_info "$@"; return $?
;;
esac
exit_abnormal() { # Function: Exit with error. exit_abnormal() { # Function: Exit with error.
usage usage
exit ${1:-1} return ${1:-1}
} }
source $BDIR/helpers.lib
scripts_dir=$SDIR/src scripts_dir=$SDIR/src
[[ -z "$PS1" ]] || no_prompt=true
while getopts ':b:d:t:ncr:u:pxhs:w:ak' OPTION; do while getopts ':b:d:t:ncr:u:pxhs:w:akvo' OPTION; do
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND} # echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
case "$OPTION" in case "$OPTION" in
o)
overwrite=true
;;
v)
verbose=true
;;
a) a)
# automated - script is to be run without prompt (non-interactive) # automated - script is to be run without prompt (non-interactive)
no_prompt=true no_prompt=true
@ -105,15 +113,15 @@ done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
target=${1:-dev} target=${1:-dev}
LINUX_DISTRO=${LINUX_DISTRO:-alpine} LINUX_DISTRO=${LINUX_DISTRO:-alpine}
name=$2 name=$2
RUSER=${3:-$RUSER} RUSER=${3:-$RUSER}
IMAGE_NAME=$([[ $RUSER ]] && echo ${RUSER}/)${name}$([[ (! $exclude_distro) && $name ]] && echo "-")$([[ ! $exclude_distro ]] && echo ${LINUX_DISTRO}) IMAGE_NAME=$([[ $RUSER ]] && echo ${RUSER}/)${name}$([[ (! $exclude_distro) && $name ]] && echo "-")$([[ ! $exclude_distro ]] && echo ${LINUX_DISTRO})
# TODO writing to existing tag untags existing image so write a new tag to that image then continue
# [[ $(image_exists $IMAGE_NAME) ]] && [[ ! $overwrite ]] && { echo local image \'$(make_tag $IMAGE_NAME)\' exists use -o to overwrite; return 1; }
if [[ $BASE_IMAGE ]]; then if [[ $BASE_IMAGE ]]; then
echo determining DISTRO of base image: $BASE_IMAGE echo determining DISTRO of base image: $BASE_IMAGE
LINUX_DISTRO=$(get_distro -d $BASE_IMAGE) LINUX_DISTRO=$(get_distro -d $BASE_IMAGE)
@ -132,18 +140,23 @@ export LINUX_DISTRO
export SCRIPTS export SCRIPTS
export KEEP export KEEP
echo " ******************************************" echo "******************************************"
echo "Building with base image: $BASE_IMAGE, output image name => $IMAGE_NAME" echo "Building with base image: $BASE_IMAGE"
echo "Outputing to image name => $IMAGE_NAME"
echo "Linux Distro: $LINUX_DISTRO" echo "Linux Distro: $LINUX_DISTRO"
echo "Using build target: $target" echo "Using build target: $target"
docker buildx bake --print $target if [[ $verbose ]]; then
echo -e "\n---------------------------------" echo -e "\n---------------------------------"
echo "build scripts at $scripts_dir to be copied to ${SCRIPTS:-/opt/build} in container ***** " docker buildx bake --print $target
ls -la $scripts_dir echo -e "\n---------------------------------"
echo -e "\n----- base init script init.sh ------" echo "build scripts at $scripts_dir to be copied to ${SCRIPTS:-/opt/build} in container ***** "
cat $scripts_dir/init.sh ls -la $scripts_dir
echo -e "\n---------------------------------" echo -e "\n----- base init script init.sh ------"
cat $scripts_dir/init.sh
echo -e "\n---------------------------------"
fi
echo -e "\n***************************************" echo -e "\n***************************************"
if [[ ! $no_prompt ]]; then if [[ ! $no_prompt ]]; then
read -n 1 -p "do you want to continue [y]=>" REPLY read -n 1 -p "do you want to continue [y]=>" REPLY
[[ $REPLY != "y" ]] && echo -e "\n" && exit 0 [[ $REPLY != "y" ]] && echo -e "\n" && exit 0
@ -186,7 +199,15 @@ if [[ $target == "private" ]]; then
fi fi
fi fi
[[ ($try || $target == "dev") ]] && ./try $([[ $target == "deploy" ]] && echo -p) $IMAGE_NAME if [[ ($try || $target == "dev") ]] && [[ ! $no_prompt ]]; then
echo trying newly built image in a container
try_container $([[ $target == "deploy" ]] && echo -p) $IMAGE_NAME
fi
popd > /dev/null popd > /dev/null
#echo reset to calling directory $PWD #echo reset to calling directory $PWD
}
# if script was executed then call the function
(return 0 2>/dev/null) || docker_image_build $@

View File

@ -1,6 +0,0 @@
#!/bin/sh
echo alpine distro uci script
apk update; apk upgrade;
echo ">>>> installing packages => $(cat packages) $(cat common-packages)"
apk add --no-cache bash bash-completion $(cat packages) $(cat common-packages)
# apk add bindfs --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing

View File

@ -1 +0,0 @@
gpg

View File

@ -1,3 +0,0 @@
tag=$(./make-tag $@)
info=$(docker image inspect $tag)
echo $info | jq '.[] | .Architecture'

View File

@ -1,4 +0,0 @@
docker run -it $1 /bin/sh -c "cat /etc/os-release" > /tmp/container-os.tmp 2> /dev/null
. /tmp/container-os.tmp
echo $ID
rm /tmp/container-os.tmp

View File

@ -1,12 +0,0 @@
#!/bin/bash
[[ $1 == "-k" ]] && key=$2 && shift 2
tag=$(./make-tag $@)
info=$(docker image inspect $tag 2> /dev/null) || info=$(docker image inspect $1) ||
exit
if [[ $key ]]; then
# echo image: $tag, key:$key
echo $info | jq --arg k "$key" '.[] | .[$k]'
else
# quote to preserve newlines
echo "$info"
fi

291
lib/file.mod Normal file
View File

@ -0,0 +1,291 @@
#!/bin/bash
# TODO allow debug to have managment flags and levels
function debug () {
[[ $BASH_DEBUG ]] && echo -e "#### DEBUG ####\n $@ \n#####" >&2
}
# alias debug_on="sudo -i uncomment BASH_DEBUG /etc/bash.bashrc"
# alias debug_off="sudo -i comment BASH_DEBUG /etc/bash.bashrc"
# *************** DEBUGGING ***********************
# module_load debug
# if [[ $? -ne 0 ]]; then
# echo "unable to load a 'debug' module using a noop for debug function"
# # noop
# function debug () {
# :
# }
# fi
# [[ ! $- == *i* ]] && exec >> ~/logs/load.log && exec 2>&1
# export BASH_DEBUG=true
# uncomment for debugging
# echo $USER running load script in $DIR
# echo callers
# caller
# echo $(ps -o comm= $PPID)
# echo -----
# echo $BASH_SHELL_DIRS
# ******************END DEBUGGING *******************************
# ***************** LOGGING *****************
# function nilog () {
# [[ ! $- == *i* ]] && echo -e "-----\n $USER $*" &>> ~/logs/load.log
# }
# nilog "called load.sh $(date)"
# nilog caller: $(caller)
# nilog pid: $(ps -o comm= $PPID)
# *
#!/bin/bash
iecho () {
[[ ! -z "$PS1" ]] && echo $1
}
# no way to tell if sourced vs subshell
# # [[ ! -z "$PS1" ]] && [[ $SHLVL -eq 1 ]] && echo $1
# # echo [[ -z $PS1 ]]
# echo $SHLVL
# echo $$
# echo $BASHPID
# if [[ -t 1 ]]; then
# echo "Terminal"
# else
# echo "Not-a-terminal"
# fi
#!/bin/bash
# export BASH_DEBUG=true
isFile() {
if [[ -f $1 ]]
then
echo "true"
return 0
else
return 1
fi
}
build_file () {
# local file
# echo build file $1 $2
# todo merge no cr
[[ $1 == "-f" ]] && file=true && shift 1
[[ -f "$2" ]] || { iecho "output file $2 does not exist"; return 1; }
if [[ -f "$1" ]]; then
# echo adding file $1 to $2
[[ $file ]] && echo -e "\n####### ADDED $1 ########" >> $2
# remove comment lines, remove blank last line
cat "$1" | sed '/^\s*#/d' | sed '/^$/{:a;N;s/\n$//;ta}' >> $2
[[ ! $file ]] && echo -e "\n" >> $2
else iecho "no such file $1 to append to $2"
fi
}
# TODO need to test
function lines_2_str () {
[[ ! -f "$1" ]] && return 1
local str=''
# echo the lines: $lines >&2
# lines="$(cat "$1")"
while read line; do
[[ "$line" =~ ^[[:space:]]*# ]] && continue
# echo line: "${line}" >&2
str="$str ${line}"
# echo str: $str >&2
done < $1
# for line in $lines ; do
# str+='"'$line'" '
# done
echo $str
}
# find, superceeds find use `command find` to get the super
function _find () {
# USAGE
# all option arguments that contain globs/wildcards must be quoted to avoid expansion
# f sets path and file excludes from a supplied file path
# all lines ending in / will be treated as directory names to ignore, otherwise files
# p option explictly excludes paths(directories)
# d option sets the directory depth which is current directy by default, 0 is all
# x excitly excludes file globs as a string
# n inclucdes only file globs otherwise it's all except .files
# if no directory is given it will attempt to source the present working directory
# example:
# source_dir -p "archive" -x '"*.off" "*.md"' -d 0 # $DIR/$SUBDIR
local EXCLUDE_FILE
local PATHS
local NAMES
local ENAMES
local DEPTH=1
local HIDDEN
declare OPTION
declare OPTARG
declare OPTIND
while getopts 't:p:d:e:n:f:h' OPTION; do
case "$OPTION" in
t)
TYPE=$OPTARG
# echo "TYPE $TYPE"
;;
f)
EXCLUDE_FILE=$OPTARG
# echo EXCLUDE FILE $EXCLUDE_FILE >&2
;;
p)
# PATHS=("$OPTARG")
IFS=',' read -r -a PATHS <<< "$OPTARG"
# echo EXCLUDING THESE PATHS ${PATHS[*]}
;;
e)
IFS=',' read -r -a ENAMES <<< "${OPTARG}"
# echo EXCLUDING THESE FILE NAMES ${ENAMES[*]}
;;
n)
# NAMES=("$OPTARG")
IFS=',' read -r -a NAMES <<< "${OPTARG}"
# NAMES=$OPTARG
;;
d)
DEPTH=$OPTARG
# echo "SOURCING TO DEPTH (0=any)" "$DEPTH"
;;
h)
HIDDEN=true
# echo "SOURCING TO DEPTH (0=any)" "$DEPTH"
;;
*)
echo unknown option $OPTION
;;
esac
done
shift $(( OPTIND - 1 ))
local DIR
DIR="$*"
if [ ! "$DIR" ]; then
if [ -v PS1 ]; then
echo no directory provided to search
echo searching present working directory $(pwd)
read -p "Do you want to continue? " -n 1 -r
[[ $REPLY =~ ^[Yy]$ ]] && DIR=$(pwd) || return 1
else
return 1
fi
fi
[ ! -d "$DIR" ] && echo " directory $DIR does not exist, aborting" && return 1
# echo dir $DIR
local FIND
FIND="command find $DIR"
FIND+=$([ ! $DEPTH == 0 ] && echo " -maxdepth $DEPTH ")
# FIND+=" -type $([ $TYPE ] && echo "$TYPE" || echo "f")"
TYPE=${TYPE:-f}
FIND+=" -type $TYPE "
# include HIDDEN files and directories IS FALSE BY DEFULT
[[ ! $HIDDEN ]] && FIND+="! -path \"*/.*/*\" ! -name \".*\" "
local name
local path
if [[ -f $EXCLUDE_FILE ]]; then
local ignores=$(lines_2_str "$EXCLUDE_FILE")
# echo ignores: $ignores >&2
for exclude in $ignores ; do
# echo exclude: ${exclude} >&2
[[ "$exclude" == */ ]] && PATHS+=("${exclude::-1}") || ENAMES+=("$exclude")
done
fi
# echo paths ${PATHS[@]} >&2
# echo exclude names ${ENAMES[@]} >&2
set -o noglob
if [[ ${PATHS[0]} ]]; then
for path in ${PATHS[@]}; do
# echo excluding $path
FIND+=$(echo ' ! -path "*/'$path'/*"')
done
fi
if [[ ${ENAMES[0]} ]]; then
for name in ${ENAMES[@]}; do
debug excluding name "$name"
FIND+=$(echo ' ! -name '$name'')
done
fi
debug "INCLUDING ONLY THESE FILE NAMES ${NAMES[*]}"
if [[ ${NAMES[0]} ]]; then
for name in "${NAMES[@]}"; do
debug only finding $name
FIND+=$(echo " -name '${name}'")
done
fi
# if [[ $NAMES ]]; then
# debug names for find command $NAMES
# for name in $NAMES; do
# debug "xxonly finding '$name'"
# FIND+=$(set -o noglob;echo " -name '${name}'")
# done
# fi
# echo
# echo find dir: $DIR >&2
debug "find command: $FIND"
set +o noglob
local FILES
FILES=$(eval $FIND | sort)
[[ $FILES ]] && echo $FILES
return 0
}
source_dir () {
# echo passed: $*
debug function: source_dir
local FILES
FILES=$(_find "$@") # find function
# echo $FILES >&2
[[ $? -ne 0 ]] && return 1
for f in $FILES; do
# echo sourcing: $f >&2
source "$f"
done
}
prepend_file () {
# ----------------------------------------------------------------------------------------------------------------------
# usage prepend_file <somefile> <anotherfile>
# ----------------------------------------------------------------------------------------------------------------------
# Prepend the contents of <somefile> [$1], to <anotherfile> [$2], leaving the result in <anotherfile> [$2].
# insert a newline at the end of <somefile> [$1] if necessary
# ----------------------------------------------------------------------------------------------------------------------
# check # echo $1 $2
[[ -f $1 ]] || return 1
[[ -f $2 ]] || return 2
# init
tmp_fn=$( mktemp -t TEMP_FILE_prepend.XXXXXXXX )
chmod 600 "$tmp_fn"
\cp $1 $tmp_fn
sed -i '$a\' $tmp_fn
cat $2 >> $tmp_fn
\mv "$tmp_fn" "$2"
# cleanup
rm -f "$tmp_fn"
return 0
# [End]
}

4
lib/load.sh Executable file
View File

@ -0,0 +1,4 @@
declare libdir
libdir=$(dirname "$(realpath "$BASH_SOURCE")")
source $libdir/file.mod
source_dir $libdir/src

30
lib/src/01-helpers Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
function get_distro() {
/bin/cp /etc/os-release /tmp/os-release.tmp
if [[ $1 == "-d" ]]; then
shift 1
# docker run -it --name get_container_os --rm --entrypoint cat $1 /etc/os-release
docker create --name dummy $1 > /dev/null
docker cp -L dummy:/etc/os-release /tmp/os-release.tmp
docker rm -f dummy > /dev/null
# docker run -it --name get_container_os --rm --entrypoint cat $1 /etc/os-release > /tmp/container-os.tmp 2> /dev/null
shift 1
fi
source /tmp/os-release.tmp
declare valid=${@:-"alpine debian ubuntu"}
# echo $ID $ID_LIKE
[[ "${valid}" =~ $ID ]] && echo $ID && return 0
[[ "${valid}" =~ $ID_LIKE ]] && echo $ID_LIKE && return 0
return 1
}
isAbsPath() {
if [[ "${1:0:1}" == / || "${1:0:2}" == ~[/a-z] ]]
then
echo "true"
return 0
else
return 1
fi
}

View File

@ -1,8 +1,11 @@
#!/bin/bash #!/bin/bash
make_tag () {
local DIR
DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P ) DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P )
#tags an image and pushes it to a <custom private> repository # generate a full image name with tag
# if not reposity is given will use docker.io and push to hub.docker.com
# $1 name, $2 user(or repo), $3 repo # $1 name, $2 user(or repo), $3 repo
[[ $# -lt 1 ]] && echo "image base name required" && exit [[ $# -lt 1 ]] && echo "image base name required" && exit
@ -44,3 +47,7 @@ tag=$([[ $repo ]] && echo ${repo}/)$([[ $user ]] && echo ${user}/)$name$([[ $arm
echo $tag echo $tag
}
# if script was executed then call the function
(return 0 2>/dev/null) || make_tag $@

28
lib/src/image-info Executable file
View File

@ -0,0 +1,28 @@
#!/bin/bash
image_info () {
[[ $1 == "-k" ]] && key=$2 && shift 2
tag=$(make_tag "$@")
info=$(docker image inspect $tag 2> /dev/null) || info=$(docker image inspect $1 2> /dev/null) || return 1
if [[ $key ]]; then
# echo image: $tag, key:$key
echo $info | jq --arg k "$key" '.[] | .[$k]'
else
# quote to preserve newlines
echo "$info"
fi
}
image_exists () {
image_info -k RepoTags "$@"
}
image_arch () {
image_info -k Architecture "$@"
}
image_id () {
image_info -k Id "$@" | sed 's/.*\://' | sed 's/"//'
}
# if script was executed then call the function
(return 0 2>/dev/null) || image_info $@

View File

@ -1,4 +1,8 @@
#!/bin/bash #!/bin/bash
image_push () {
local DIR
DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P ) DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P )
#tags an image and pushes it to a <custom private> repository #tags an image and pushes it to a <custom private> repository
@ -83,3 +87,8 @@ fi
echo removing tag $target echo removing tag $target
docker image rm $target > /dev/null 2>&1 docker image rm $target > /dev/null 2>&1
}
# if script was executed then call the function
(return 0 2>/dev/null) || image_push $@

34
lib/src/image-tag Executable file
View File

@ -0,0 +1,34 @@
#!/bin/bash
image_tag () {
local DIR
DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P )
# tags an image
# -d -f <imagetag or id> <newimagetag>
[[ $# -lt 1 ]] && echo "image base name required" && exit
[[ $1 == "-d" ]] && delete=true && shift 1
[[ $1 == "-f" ]] && force=true && shift 1
[[ $1 == "-i" ]] && { shift 1; id=$1; } || id=$(image_id $1)
[[ ! $id ]] && { echo "no image with id $id $(make_tag "@")"; return 1; }
[[ $force ]] && docker rmi -f $id && return 0
if [[ $delete ]];then
docker rmi $id
else
docker tag $id $(make_tag $2)
fi
echo tags after operation for image $id
image_info -k RepoTags $id
}

96
lib/src/try Executable file
View File

@ -0,0 +1,96 @@
#!/bin/bash
# starts a trail container with passed image with a bash prompt
# $1 image name, $2 user
# user can be also prepended by using u option
# added tag is "latest" by default, use t option for alternate tag
# if p flag is used script will scrub any local image and attempt to download a deployed to docker image
try_container () {
declare -A arch=( ["x86_64"]="" ["aarch64"]="-arm64")
[[ $# -lt 1 ]] && echo "image name required to try" && return 1
declare OPTION; declare OPTARG; declare OPTIND
OPTIND=0
while getopts 'pt:u:' OPTION; do
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
case "$OPTION" in
u)
ruser=$OPTARG
;;
t)
TAG=$OPTARG
;;
p)
PROD=$OPTARG
;;
*) echo unknown run option -$OPTARG
echo "USAGE: try <options>"
echo "available options: -t <latest> custom tag "
;;
esac
done
shift $((OPTIND - 1))
user=${2:-$ruser}
image=$([[ $user ]] && echo ${user}/)$1
# :${TAG:-latest}
if [[ $PROD ]]; then
echo removing any local copy of image $image
docker image rm $image
host=prod
else
host=local
# TODO change this
image=${image/:/${arch[$(uname -p)]}:}
fi
name=${image//\//-}
image=$image:${TAG:-latest}
bmount () {
[[ $1 == "-u" ]] && umount=true && shift
declare mp=${1:-opt}
declare dir=${2:-${PWD}/_$mp}
vname=try-$name-$mp
if [[ $umount ]]; then
echo removing volume ....
docker volume rm $vname
echo "volume $vname was removed"
echo "Do you want to also delete the bound volume directory $dir?"
read -n 1 -p "Warning: ALL changes in $mp directory in container will be lost! [y]=>" REPLY
[[ $REPLY != "y" ]] && echo -e "\n" && exit 0
sudo rm -rf $dir
else
mkdir -p $dir
docker volume create --driver local \
--opt type=none \
--opt device=$dir \
--opt o=bind \
$vname
# echo "type=volume,dst=/$mp,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=$dir"
fi
}
echo starting container with image: $image, and name $name
echo at container prompt type \'exit\' to exit from shell and remove trial container
docker rm try-$name > /dev/null 2>&1
docker run -i -t --rm --entrypoint /usr/bin/env --name try-$name --hostname try-$host-$name \
-v "$(bmount)":/opt \
$image \
/bin/bash -l
echo "done with session, removing containter try-$name"
bmount -u
}
# if script was executed then call the function
(return 0 2>/dev/null) || try_container $@

18
lib/src/usage Normal file
View File

@ -0,0 +1,18 @@
#!/bin/bash
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 <setup options> buildtarget <imagename, imageuser>"
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 <LINUX_DISTRO> supported: alpine, debian, ubuntu, default: alpine; if base image set distro will be determined"
echo "-t <TAG> tag following : in output image name (i.e. REPO/USER/NAME:TAG), default: latest"
echo "-u <USER>; repository user prefix in output image name (i.e. REPO/USER/NAME:TAG)"
echo "-r <REPO>; private repo name, do not use for hub.docker.com (docker.io)"
echo "-b <BASE_IMAGE>; used in FROM in Dockerfile, default is official distro image (e.g. alpine:latest)"
echo "-w <SCRIPTS>; set a custom WORKDIR in Dockerfile, default is /opt/build"
}

View File

@ -1,8 +1,8 @@
# UCI Docker Image Builder # UCI Docker Image Builder
A set of scripts to facilitate building docker linux (amd64/arm64) images using any of three distros (alpine,debian,ubuntu) A build script plus associated library to facilitate building docker linux images using any of three distros (alpine,debian,ubuntu) and either architecture (amd64/arm64)
The Dockerfile is minimal calling a set of distro specific scripts and common scripts in order to build the image The Dockerfile is minimal, calling a set of distro specific scripts and common scripts in order to build the image
The build environment makes user of docker's "buildx bake" commands and a docker-bake.hcl file The build environment makes user of docker's "buildx bake" commands and a docker-bake.hcl file
@ -10,11 +10,17 @@ The master branch is configured to build base images from the docker hub distro
The main script is "build" At the very minimum run as just `./build` it will build an alpine image from the docker hub official alpine latest image with a minimal set of packages installed (e.g. git) and a custom uci shell environment. The main script is "build" At the very minimum run as just `./build` it will build an alpine image from the docker hub official alpine latest image with a minimal set of packages installed (e.g. git) and a custom uci shell environment.
By using the -b flag you can set an alternative FROM image. In this way you can make your own script that builds multiple tiers of images The repo also supports (with scripts) pushing to alternate private repositories packages (like a self hosted gitea or github)
The repo also supports (with scripts) pushing to alternate private repositories (like self hosted gitea) One can make decendent images in one of two way.
1. Make your base images on the master branch then create a new branch and edit the script files in the src folder
3. User the installer script (./install) to install to link the build script into your system path. Then clone the template branch
the build script requires an init.sh file in a source directory for the scripts it will run while building a new image
by default that is `<source directory>/init.sh`. by default that source directory is `src/` relative to the current directory
starting a new branch is a good way to work on a new image by editing the script files in the src folder

8
src/alpine/init.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/sh
echo alpine distro init script
apk update; apk upgrade;
pwd; ls -la
echo ">>>> installing packages => alpine: $(cat ./packages); common: $(cat ../common/packages)"
apk add --no-cache bash bash-completion $(cat ./packages) $(cat ../common/packages)
# apk add bindfs --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing

1
src/alpine/packages Normal file
View File

@ -0,0 +1 @@
bash

0
src/common/adduser.sh Normal file
View File

View File

@ -2,3 +2,4 @@
wget -O /opt/scripts/info https://git.io/vaHfR; wget -O /opt/scripts/info https://git.io/vaHfR;
chmod +x /opt/scripts/info chmod +x /opt/scripts/info
ln -s /opt/scripts/info /opt/bin ln -s /opt/scripts/info /opt/bin
/opt/bin/info

View File

@ -1,12 +1,10 @@
#!/bin/bash #!/bin/bash
echo -e "\n##################################" echo -e "\n##################################"
mkdir -p /opt/scripts /opt/bin /shell /data mkdir -p /opt/scripts /opt/bin /shell /opt/conf /data
# this is the default host user
chown -R 1000:1000 /opt /shell /data
git clone https://git.kebler.net/bash/shell-base.git /shell/base git clone https://git.kebler.net/bash/shell-base.git /shell/base
cp ucishell.sh /shell/base/setup cp ucishell.sh /shell/base/setup
/shell/base/setup/ucishell.sh /shell/base/setup/ucishell.sh
if [[ -f post_common.sh ]]; then
echo "running distro specific commands after common install in post_common.sh"
./post_common.sh
fi
# install and display distro info # install and display distro info
./info.sh ./info.sh

170
src/common/user.sh Executable file
View File

@ -0,0 +1,170 @@
#!/bin/bash
# clone a user
# adduserid name id#
# add a suer with specific id number
# adduserid () {
# sudo groupadd -g $2 $1
# sudo useradd -d ${/home/$1} -s /bin/bash -u $2 -g $1 $1
# }
adduserid() {
[[ "$#" -lt 1 ]] && echo a user name is requied, aborting && return 1
name=$1
uid=${2:-1000}
gid=${3:-$uid}
echo $name, $uid, $gid
[[ $(getent group $gid) ]] && echo group id $gid already exists, aborting && return 3
[[ $(getent group $name) ]] && echo group name $name already exists, aborting && return 3
[[ $(getent passwd $uid) ]] && echo user id $uid already exists, aborting && return 2
[[ $(getent passwd $name) ]] && echo user name $name already exists, aborting && return 2
echo addgroup --gid $gid $name
echo adduser -u $uid -G $name -g "" -D -H $name
# cat /etc/group | grep $name && cat /etc/passwd | grep $name
}
function clone_user_ () {
module_load confirm
echo "============="
echo "this script will create a new user"
echo "based on an existing user's data"
echo
echo "You will be shown a list of users who can currently log on"
echo "Remember which user you would like to clone."
echo "You will be asked for the new user's name, their password"
echo "and the old user to clone".
echo "============="
echo
echo -n "New user's name: "
read newuser
echo -n "New user's password: "
read newpassword
echo
echo "Current users you can clone:"
echo "----"
awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' /etc/passwd
echo
echo -n "Old user to clone: "
read olduser
echo "olduser uid is $(id -u $olduser)"
echo
echo "You have selected: "
echo "----"
echo "new user: $newuser"
echo "new user password: $newpassword"
echo "old user: $olduser"
echo
olduser_GROUPS="$(id -Gn ${olduser} | sed "s/${olduser} //g" | sed "s/ ${olduser}//g" | sed "s/ /,/g"),$olduser"
olduser_SHELL=$(awk -F : -v name=${olduser} '(name == $1) { print $7 }' /etc/passwd)
echo "old user groups: "
echo "----"
echo $olduser_GROUPS
echo "olduser shell: "
echo $olduser_SHELL
confirm "ready to clone user, begin?" || return 1
useradd --groups $olduser_GROUPS --shell $olduser_SHELL $newuser
echo $newuser:$newpassword | chpasswd
read -rsp $'ready to make home direcoty -- ctrl-c to exit...\n' -n1 key
mkdir /home/$newuser
chown -R $newuser:$newuser /home/$newuser
echo
echo "Script should be done now."
echo
echo "Do you see your new users name below?"
echo
awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' /etc/passwd
echo
echo "We are now going to copy the old user's home folder to the new user"
echo "then change ownership to the new user"
echo
read -rsp $'Ready to copy home folder --- or ctrl-c to exit...\n' -n1 key
rsync -aPv --exclude 'Downloads' /home/$olduser/. /home/$newuser/
chown -R --from=$olduser $newuser:$newuser /home/$newuser
echo
echo "Now we are going to change the names of files and folders to the new user"
echo
grep -rlI $olduser /home/$newuser/ . | sudo xargs sed -i 's/$olduser/$newuser/g'
echo
echo "Done now."
echo
read -rsp $'Press any key to exit...\n' -n1 key
echo
echo
}
clone_user () {
if [[ $EUID != 0 ]]; then
clone=$(declare -f clone_user_)
module_load confirm
confirm=$(declare -f confirm)
sudo bash -c "$confirm; $clone; clone_user_"
else
echo run as regular user with sudo privliges and it will elevate
fi
}
rename_user () {
module_load confirm
local force; local name; local newname; local newhome
[[ $1 = "-f" ]] && { force=true; shift 1; }
[[ $1 = "-h" ]] && { newhome=$2; shift 2; }
# usage: < -f, -h newhome > name newname
# default new user home is /home/newname
name=$1
newname=$2
if [[ ! ($name && $newname) ]]; then
echo "============="
echo "this script will rename an existing user"
echo "user running this script must to root or have sudo priviledges to run"
echo "---- Available Users to Rename ---"
awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' /etc/passwd
echo "============="
read -r -p "Enter an available user name: " name
read -r -p "Enter users new name: " newname
read -r -p "Enter users new home directory <enter for default /home/$newname>: " newhome
fi
newhome=${newhome:-/home/$newname}
if [[ ! $force ]]; then
echo "Changing $name to $newname with home $newhome"
echo sudo usermod -l $newname $name
echo sudo groupmod -n $newname $name
echo sudo usermod --d $newhome --m $name
confirm -s "These are the commands that will be run. Do you want to continue?" || return 1
fi
sudo usermod -l $newname $name
echo sudo groupmod -n $newname $name
echo sudo usermod --d $newhome --m $name
}

23
src/init.sh Normal file
View File

@ -0,0 +1,23 @@
#!/bin/sh
echo "entry init.sh script in $PWD"
# remove other distro files
find $PWD -maxdepth 1 -type d ! -path $PWD ! -name ${LINUX_DISTRO} ! -name common -exec rm -rf {} +
cd ${LINUX_DISTRO} || exit 1
echo " ----- Running ${LINUX_DISTRO} specific init script ----- ";
./init.sh
cd ..
cd common || exit 1
echo " ***** Running common initialzation script *****"
ls -la;
./init.sh;
cd ${LINUX_DISTRO} || exit 1
echo " ----- Running ${LINUX_DISTRO} specific post commont script ----- ";
if [[ -f post_common.sh ]]; then
echo "running distro specific commands after common install in post_common.sh"
./post_common.sh
fi
echo returned from ${LINUX_DISTRO} post common script
if [ -z $KEEP ]; then
echo removing $SCRIPTS directory used for build
cd /opt && rm -rf $SCRIPTS
fi

View File

@ -2,5 +2,5 @@
echo ubuntu distro uci script echo ubuntu distro uci script
apt-get update apt-get update
echo ">>>> installing packages => $(cat packages) $(cat common-packages)" echo ">>>> installing packages => $(cat packages) $(cat common-packages)"
apt-get install $(cat packages) $(cat common-packages) -y apt-get install $(cat packages) $(cat ../common/packages) -y
./add-ppa.sh -i -p git git-core/ppa ./add-ppa.sh -i -p git git-core/ppa

2
src/ubuntu/packages Normal file
View File

@ -0,0 +1,2 @@
ca-certificates
gpg

28
tag
View File

@ -1,28 +0,0 @@
#!/bin/bash
DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P )
#tags an image and pushes it to a <custom private> repository
# if not reposity is given will use docker.io and push to hub.docker.com
# $1 name, $2 user(or repo), $3 repo
[[ $# -lt 1 ]] && echo "image base name required" && exit
[[ $1 == "-d" ]] && delete=true && shift 1
[[ $1 == "-f" ]] && force=true && shift 1
[[ $force ]] && docker rmi -f $(docker images -q $(./make-tag $@)) && exit 0
if [[ $delete ]];then
id=$(docker images -q $(./make-tag $@))
docker rmi $(./make-tag $@)
else
docker tag $(./make-tag $1) $(./make-tag $2)
id=$(docker images -q $(./make-tag $2))
fi
echo tags after operation for image $id
./image-info -k RepoTags $id

62
try
View File

@ -1,62 +0,0 @@
#!/bin/bash
file=try.yml
DIR=$(cd "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 ; pwd -P )
#tags an images and pushes it to a <custom private> repository
# if not reposity is given will use docker.io and push to hub.docker.com
# $1 name, $2 user
declare -A arch=( ["x86_64"]="" ["aarch64"]="-arm64")
[[ $# -lt 1 ]] && echo "image name required to try" && exit
declare OPTION; declare OPTARG; declare OPTIND
while getopts 'pt:u:' OPTION; do
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
case "$OPTION" in
u)
RUSER=$OPTARG
;;
t)
TAG=$OPTARG
;;
p)
PROD=$OPTARG
;;
*) echo unknown run option -$OPTARG
echo "USAGE: try <options>"
echo "available options: -t <latest> custom tag "
;;
esac
done
shift $((OPTIND - 1))
# build up package tag
name=$1
user=${2:-$RUSER}
image=$([[ $user ]] && echo ${user}/)$name:${TAG:-latest}
if [[ $PROD ]]; then
echo removing any local copy of image $image
docker image rm $source
HOST=prod
else
HOST=local
image=${image/:/${arch[$(uname -p)]}:}
fi
echo starting container with image $image
export IMAGE=$image
export HOST
shopt -s extglob
export NAME=${image//+([^A-Za-z0-9])/-}
docker-compose -f $file down;
docker-compose -f $file up -d;
docker exec -it try-$NAME /bin/bash -l
docker-compose -f $file down;
# return to starting directory
# popd

View File

@ -1,8 +0,0 @@
version: "3"
services:
uci:
image: $IMAGE
container_name: try-$NAME
hostname: try-$HOST-$NAME
command: ["sleep", "infinity"]