refactor: generate Dockerfile from a template
refactor src/ to be just a basic build add examples write up help.md and usage subcommand add test folder for dev testing improve install script many numerous improved to build script, moved portions of build script to functions in helpers.libmaster
parent
16bc3bd929
commit
efe8d0fa2d
|
@ -5,3 +5,5 @@ _opt/
|
|||
TODO.md
|
||||
mnt/
|
||||
logs/
|
||||
Dockerfile
|
||||
.env
|
63
Dockerfile
63
Dockerfile
|
@ -1,63 +0,0 @@
|
|||
# syntax=docker/dockerfile:latest
|
||||
ARG BASE_IMAGE
|
||||
FROM $BASE_IMAGE
|
||||
ARG BASE_IMAGE
|
||||
ARG SYSADMIN_PW
|
||||
ARG LINUX_DISTRO=alpine
|
||||
WORKDIR /build
|
||||
|
||||
# PACKAGES
|
||||
RUN --mount=type=bind,source=.src/packages,target=/build/packages \
|
||||
<<eot
|
||||
echo -e "\n ************************************************* \n"
|
||||
echo "Building Image from Base: $BASE_IMAGE"
|
||||
echo "Distro: $LINUX_DISTRO; *****"
|
||||
echo " ---- running packages install script ---"
|
||||
cd packages; /bin/sh ./packages.sh; cd ..
|
||||
echo -e "\n********************************************************"
|
||||
eot
|
||||
# END PACKAGES
|
||||
|
||||
# INITIALIZATION
|
||||
RUN --mount=type=bind,source=.src/init,target=/build/init \
|
||||
<<eot
|
||||
echo -e "\n ************************************************* \n"
|
||||
echo "****** Initializing Image with build source ******"
|
||||
cd init
|
||||
pwd; ls -la
|
||||
if [[ -d env/ ]]; then
|
||||
echo "copying env/ to /opt/env"
|
||||
/bin/cp -R -p env/. /opt/env
|
||||
ls -la /opt/env
|
||||
fi
|
||||
if [[ -f env/build.env ]]; then
|
||||
source /opt/env/build.env
|
||||
rm -f /opt/env/build.env
|
||||
echo sourced /opt/env/build.env and deleted
|
||||
fi
|
||||
if [[ -d bin/ ]]; then
|
||||
echo "copying bin/ to /opt/bin"
|
||||
/bin/cp -R -p bin/. /opt/bin
|
||||
chmod -R +x /opt/bin
|
||||
ls -la /opt/bin
|
||||
fi
|
||||
echo " ---- running init script init.sh ---"
|
||||
/bin/bash ./init.sh
|
||||
echo "############## Finished run init build script(s) ###########################"
|
||||
if [[ -f /opt/env/run.env ]]; then
|
||||
echo "sourcing /opt/env/run.env from /etc/profile"
|
||||
echo "&&&&&& last 10 of /etc/profile &&&&&"
|
||||
echo -e "# added from image build\nsource /opt/env/run.env" >> /etc/profile
|
||||
tail /etc/profile
|
||||
echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
||||
fi
|
||||
echo -e "\n ************* End Initialzation ************************"
|
||||
eot
|
||||
# END INITIALIZATION
|
||||
|
||||
# default command
|
||||
CMD ["/bin/bash", "-l"]
|
||||
# default
|
||||
WORKDIR /opt
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# syntax=docker/dockerfile:latest
|
||||
ARG BASE_IMAGE
|
||||
FROM $BASE_IMAGE
|
||||
ARG BASE_IMAGE
|
||||
ARG SYSADMIN_PW
|
||||
ARG VERBOSE
|
||||
ARG LINUX_DISTRO=alpine
|
||||
WORKDIR /build
|
||||
|
||||
# PACKAGES
|
||||
RUN --mount=type=bind,source=.src/packages,target=/build/packages \
|
||||
<<eot
|
||||
.INCLUDE packages.tpl
|
||||
eot
|
||||
# END PACKAGES
|
||||
|
||||
# INITIALIZATION
|
||||
RUN --mount=type=bind,source=.src/init,target=/build/init \
|
||||
<<eot
|
||||
.INCLUDE init.tpl
|
||||
eot
|
||||
|
||||
# END INITIALIZATION
|
||||
|
||||
# default command
|
||||
ENTRYPOINT ["/opt/bin/entrypoint"]
|
||||
# default
|
||||
WORKDIR /opt
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
pushd $(dirname "$(realpath "$BASH_SOURCE")") > /dev/null || return 1
|
||||
source <(../lib/bash-tpl Dockerfile.tpl ) | grep -v '^# ' > ../Dockerfile
|
||||
echo " ************* uci build Dockerfile created *****************"
|
||||
popd > /dev/null || return 2
|
|
@ -0,0 +1,86 @@
|
|||
#!/bin/bash
|
||||
%
|
||||
if [[ $REBUILD == "init" ]]; then
|
||||
echo "## Busting Cache, Forcing Rebuild $(date)"
|
||||
fi
|
||||
%
|
||||
quiet () {
|
||||
if [[ $VERBOSE ]]; then $@; fi
|
||||
}
|
||||
quiet echo -e "\n ************************************************* \n"
|
||||
quiet echo "****** Initializing Image with build source ******"
|
||||
cd init
|
||||
pwd; quiet ls -la
|
||||
export BUILDING=true
|
||||
export BUILD_DIR=$PWD
|
||||
export SHELL=/bin/bash
|
||||
export BIN_DIR=/opt/bin
|
||||
mkdir -p $BIN_DIR
|
||||
echo "export BIN_DIR=${BIN_DIR}" >> /tmp/profile
|
||||
echo 'export PATH=$BIN_DIR:$PATH' >> /tmp/profile
|
||||
|
||||
echo " ##### creating entrypoint script ###"
|
||||
cat << EOE >$BIN_DIR/entrypoint
|
||||
.INCLUDE ./init/entrypoint.tpl
|
||||
EOE
|
||||
chmod +x $BIN_DIR/entrypoint
|
||||
quiet echo '------ default entrypoint -----'
|
||||
quiet ls -la $BIN_DIR/entrypoint
|
||||
quiet cat $BIN_DIR/entrypoint
|
||||
quiet echo "------------"
|
||||
|
||||
echo " ##### creating default start script ###"
|
||||
cat << "EOS" >$BIN_DIR/start
|
||||
.INCLUDE ./init/start.sh
|
||||
EOS
|
||||
chmod -R +x $BIN_DIR/start
|
||||
quiet echo "--- DEFAULT START SCRIPT in $BIN_DIR/start ---"
|
||||
quiet cat $BIN_DIR/start
|
||||
quiet echo "-----------------------------------"
|
||||
|
||||
echo " ##### creating map host id script ###"
|
||||
cat << "EOM" >$BIN_DIR/map-host-id
|
||||
.INCLUDE ./init/map-host-id.sh
|
||||
EOM
|
||||
chmod +x $BIN_DIR/map-host-id
|
||||
|
||||
[[ -f image.info ]] && cp image.info /opt
|
||||
|
||||
.INCLUDE ./init/dirs.sh
|
||||
|
||||
if [[ -f build.env ]]; then
|
||||
echo "-- sourcing /build/build.env --"
|
||||
quiet ls -la
|
||||
quiet cat build.env
|
||||
quiet echo "----------------------"
|
||||
source build.env
|
||||
fi
|
||||
|
||||
if [[ -f ./init.sh ]]; then
|
||||
echo "############## Running Script init.sh of build source #################"
|
||||
quiet echo "----- build environment ------"
|
||||
quiet env
|
||||
quiet echo "----- env ------"
|
||||
quiet echo "-------------------- init.sh ------------------------------"
|
||||
quiet cat ./init.sh
|
||||
quiet echo "-------------------------------------------------------------"
|
||||
# init.sh must have shebang and be executable
|
||||
if ! $SHELL ./init.sh; then return 1; fi
|
||||
echo "############## Finished running init.sh build script #########################"
|
||||
fi
|
||||
|
||||
.INCLUDE ./init/profile.sh
|
||||
|
||||
echo "****** creating user and group 'host' with ids 1000 *****"
|
||||
groupadd -g 1000 host
|
||||
useradd -r -g host -u 1000 host
|
||||
# map host id now based on build environment
|
||||
if [[ $VOLUME_DIRS ]]; then
|
||||
echo "*** creating and configuring volume directories ***"
|
||||
echo $VOLUME_DIRS
|
||||
mkdir -p $VOLUME_DIRS
|
||||
$BIN_DIR/map-host-id
|
||||
chmod -R g+rw $VOLUME_DIRS
|
||||
fi
|
||||
|
||||
echo -e "\n ************* End Initialzation ************************"
|
|
@ -0,0 +1,25 @@
|
|||
if [[ -d env/ ]]; then
|
||||
export ENV_DIR=/opt/env
|
||||
echo "############## Adding Environment Directroy $ENV_DIR #################"
|
||||
echo "export ENV_DIR=${ENV_DIR}" >> /tmp/profile
|
||||
quiet echo "copying env/ to $ENV_DIR"
|
||||
/bin/cp -R -p env/. $ENV_DIR
|
||||
quiet ls -la $ENV_DIR
|
||||
fi
|
||||
if [[ -d bin/ ]]; then
|
||||
echo "############## Copying to Binary Directroy $BIN_DIR #################"
|
||||
quiet echo "copying bin/ to $BIN_DIR"
|
||||
/bin/cp -R -p bin/. $BIN_DIR
|
||||
# chmod -R +x $BIN_DIR
|
||||
quiet ls -la $BIN_DIR
|
||||
fi
|
||||
|
||||
if [[ -d lib/ ]]; then
|
||||
export LIB_DIR=/opt/lib
|
||||
echo "############## Adding Library Directroy $LIB_DIR #################"
|
||||
echo "export LIB_DIR=${LIB_DIR}" >> /tmp/profile
|
||||
quiet echo "copying lib/ to $LIB_DIR"
|
||||
/bin/cp -R -p lib/. $LIB_DIR
|
||||
chmod -R +x $LIB_DIR
|
||||
quiet ls -la $LIB_DIR
|
||||
fi
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
# to maintain variable $ in container script espcape with \$
|
||||
# otherwise subtitution will happen during build
|
||||
case "\$1" in
|
||||
maphostid)
|
||||
shift 1
|
||||
/bin/bash -l -c '\$BIN_DIR/map-host-id \$@' \$0 "\$@"
|
||||
;;
|
||||
shell)
|
||||
/bin/bash -c "cd \${INITIAL_DIR:-/opt}; exec bash -l"
|
||||
;;
|
||||
help)
|
||||
.INCLUDE ./init/help.sh
|
||||
;;
|
||||
image)
|
||||
.INCLUDE ./init/image-info.sh
|
||||
;;
|
||||
script)
|
||||
shift 1
|
||||
cat | /bin/bash -l
|
||||
;;
|
||||
${ENTRYPOINT_CMD:-start})
|
||||
shift 1
|
||||
/bin/bash -l -c '${ENTRYPOINT_CMD_PATH:-$BIN_DIR/start} \$@' \$0 "\$@"
|
||||
;;
|
||||
*)
|
||||
/bin/bash -l -c '"\$@"' \$0 "\$@"
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,14 @@
|
|||
cat <<HELP
|
||||
--------- ENTRYPOINT HELP ----------
|
||||
commands are shell,maphostid,help,image and a custom command <start>
|
||||
otherwise you can pass any shell command such as 'ls -la'
|
||||
the current container custom command is > ${ENTRYPOINT_CMD:-start}
|
||||
and the script for that command is in ${ENTRYPOINT_CMD_PATH:-$BIN_DIR/start}
|
||||
-----
|
||||
you can replace this start script with your own
|
||||
your own script in $BIN_DIR/start in your build source directory
|
||||
or set the \$ENTRYPOINT_CMD and \$ENTRYPOINT_CMD_PATH variables
|
||||
It is possible to override the container entrypoint with your own
|
||||
but is not recommmended as then a login shell will not be used
|
||||
and critical environment variables will not be set
|
||||
HELP
|
|
@ -0,0 +1,5 @@
|
|||
if [[ -f /opt/image.info ]]; then
|
||||
echo -e "\n--------- image info found at /opt/image.info----------"
|
||||
cat /opt/image.info
|
||||
echo -e "\n****************************"
|
||||
fi
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
if [[ $VOLUME_DIRS ]]; then
|
||||
echo changing ownership of directories $VOLUME_DIRS
|
||||
echo to ${HOST_MAP:-"host:host"}
|
||||
declare usesudo
|
||||
[[ ! $EUID -eq 0 ]] && usesudo=sudo
|
||||
$usesudo chown -R ${HOST_MAP:-"host:host"} $VOLUME_DIRS
|
||||
ls -la $VOLUME_DIRS
|
||||
fi
|
|
@ -0,0 +1,12 @@
|
|||
[[ -f $ENV_DIR/run.env ]] && echo 'source $ENV_DIR/run.env' >> /tmp/profile
|
||||
|
||||
while read line; do
|
||||
if ! grep -q "$line" /etc/profile; then
|
||||
quiet echo added $line to /etc/profile
|
||||
echo $line >> /etc/profile
|
||||
fi
|
||||
done < /tmp/profile
|
||||
# echo "echo /etc/profile has been sourced" >> /etc/profile
|
||||
quiet echo "&&&&&&& last 10 of /etc/profile &&&&&"
|
||||
quiet tail /etc/profile
|
||||
quiet echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
#***** CONTAINER DEFAULT CUSTOM SCRIPT ******************"
|
||||
case "$1" in
|
||||
sub1)
|
||||
echo this would be a subcommand #1
|
||||
echo with arguments $@
|
||||
;;
|
||||
sub2)
|
||||
shift 1
|
||||
echo this would be a subcommand #1
|
||||
echo with arguments $@
|
||||
;;
|
||||
*)
|
||||
echo "running this command $*"
|
||||
echo within login shell
|
||||
/bin/bash -c '"$@"' $0 "$@"
|
||||
esac
|
|
@ -0,0 +1,20 @@
|
|||
%
|
||||
if [[ $REBUILD == "packages" ]]; then
|
||||
echo "## Busting Cache, Forcing Rebuild $(date)"
|
||||
fi
|
||||
%
|
||||
echo -e "\n ************************************************* \n"
|
||||
echo "Building Image from Base: $BASE_IMAGE"
|
||||
echo "Distro: $LINUX_DISTRO"
|
||||
echo " ---- running packages install script ---"
|
||||
if [[ $LINUX_DISTRO == "alpine" ]]; then
|
||||
echo "-------------------------------"
|
||||
echo "adding shadow bash and bash completion coreutils for alpine"
|
||||
echo "to be compatible with other distros"
|
||||
apk add --no-cache shadow bash bash-completion coreutils
|
||||
echo "-------------------------------"
|
||||
fi
|
||||
cd packages
|
||||
/bin/sh ./packages.sh
|
||||
cd ..
|
||||
echo -e "\n********************************************************"
|
233
build
233
build
|
@ -1,46 +1,56 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker_image_build () {
|
||||
udbuild () {
|
||||
|
||||
local targets=(dev arm64 amd64 deploy private multi)
|
||||
local verbose; local log_dir; local no_prompt
|
||||
local efile
|
||||
local targets=(dev arm64 amd64 publish multi default)
|
||||
local log_dir; local no_prompt
|
||||
local append_efile
|
||||
declare OPTION; declare OPTARG; declare OPTIND
|
||||
|
||||
BDIR=$(dirname "$(realpath "$BASH_SOURCE")")
|
||||
export BDIR
|
||||
# load script library
|
||||
source $BDIR/lib/load.sh
|
||||
BUILD_EFILE=""
|
||||
|
||||
# check for subcommands first
|
||||
case "$1" in
|
||||
try)
|
||||
shift 1
|
||||
# type try_container
|
||||
try_container "$@"
|
||||
shift 1; try_container "$@"; return $? ;;
|
||||
load_env_file)
|
||||
echo -e "@@@@@@ loading build environment file for external use @@@@@@"
|
||||
BUILD_EFILE=$(echo -- "$@" | grep -oP -- '(?<=-e )[^ ]*')
|
||||
source_env_file "$BUILD_EFILE"
|
||||
echo -e "@@@@@@@@@@@@@@@@@ returning to calling script @@@@@@@@@@@@@@@"
|
||||
return $?
|
||||
;;
|
||||
image_name)
|
||||
build_src) shift 1; get_build_src "$@"; return $? ;;
|
||||
help)
|
||||
;&
|
||||
--help)
|
||||
;&
|
||||
-help) shift 1; usage "$@"; return $? ;;
|
||||
source) type udbuild; return $? ;;
|
||||
image)
|
||||
shift 1
|
||||
image_name "$@"
|
||||
return $?
|
||||
;;
|
||||
tag)
|
||||
shift 1
|
||||
image_tag "$@"
|
||||
return $?
|
||||
;;
|
||||
push)
|
||||
shift 1
|
||||
image_push "$@"
|
||||
return $?
|
||||
;;
|
||||
case "$1" in
|
||||
name) shift 1; image_name "$@" ;;
|
||||
tag) shift 1; image_tag "$@" ;;
|
||||
push) shift 1; image_push "$@" ;;
|
||||
delete) shift 1; image_delete "$@" ;;
|
||||
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 $?
|
||||
case "$1" in
|
||||
arch) shift 1; image_arch "$@" ;;
|
||||
exists) shift 1; image_exists "$@" ;;
|
||||
tags) shift 1; image_tags "$@" ;;
|
||||
id) shift 1; image_id "$@" ;;
|
||||
* ) image_info "$@"
|
||||
esac
|
||||
;;
|
||||
*) echo no image subcommand $1 ;;
|
||||
esac
|
||||
return $?
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -52,20 +62,30 @@ exit_abnormal() { # Function: Exit with error.
|
|||
[[ -z "$PS1" ]] || no_prompt=true
|
||||
overwrite=true
|
||||
|
||||
while getopts 'g:e:b:d:t:ncr:u:plhs:avo' OPTION; do
|
||||
while getopts 'fg:e:b:d:t:nc:r:u:lhs:a:voi:p' OPTION; do
|
||||
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
|
||||
case "$OPTION" in
|
||||
i)
|
||||
IMAGE_INFO=$OPTARG
|
||||
;;
|
||||
e)
|
||||
if source_env_file $OPTARG; then efile=true; else return 2; fi
|
||||
BUILD_EFILE=$OPTARG
|
||||
if ! source_env_file $BUILD_EFILE; then return 2; fi
|
||||
;;
|
||||
o)
|
||||
unset overwrite
|
||||
;;
|
||||
v)
|
||||
verbose=true
|
||||
VERBOSE=true
|
||||
;;
|
||||
a)
|
||||
# automated - script is to be run without prompt (non-interactive)
|
||||
append_efile=$OPTARG
|
||||
;;
|
||||
f)
|
||||
REBUILD=init
|
||||
;;
|
||||
p)
|
||||
echo "build script will be run WITHOUT user prompts (i.e. non-interactive)"
|
||||
no_prompt=true
|
||||
;;
|
||||
b)
|
||||
|
@ -82,7 +102,7 @@ while getopts 'g:e:b:d:t:ncr:u:plhs:avo' OPTION; do
|
|||
;;
|
||||
l)
|
||||
# append distro name to image name
|
||||
append_distro=true
|
||||
APPEND_DISTRO=true
|
||||
;;
|
||||
t)
|
||||
TARGET=$OPTARG
|
||||
|
@ -94,10 +114,7 @@ while getopts 'g:e:b:d:t:ncr:u:plhs:avo' OPTION; do
|
|||
RUSER=$OPTARG
|
||||
;;
|
||||
c)
|
||||
try=true
|
||||
;;
|
||||
p)
|
||||
push=true
|
||||
TRY_CMD=$OPTARG
|
||||
;;
|
||||
n)
|
||||
nocache="--no-cache"
|
||||
|
@ -118,70 +135,27 @@ done
|
|||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
[[ ! $efile ]] && source_env_file
|
||||
[[ ! $BUILD_EFILE ]] && source_env_file
|
||||
|
||||
# processing the build source directory
|
||||
if [[ ! $BUILD_SRC ]]; then
|
||||
echo no BUILD_SRC directory specified
|
||||
echo using present directory $PWD
|
||||
BUILD_SRC=$PWD
|
||||
fi
|
||||
|
||||
if [[ ! $(isAbsPath $BUILD_SRC) ]] ; then
|
||||
if [[ ${BUILD_SRC} == "_base_" ]]; then
|
||||
BUILD_SRC=${BDIR}/src
|
||||
else
|
||||
BUILD_SRC=$(realpath ${BUILD_SRC})
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! ( -d $BUILD_SRC/packages && -d $BUILD_SRC/init ) ]]; then
|
||||
echo -e "\e[1;31minvalid build source directory"
|
||||
echo $BUILD_SRC
|
||||
echo -e "it does not contain packages and init subirectories\e[1;37m"
|
||||
if [[ ! $(basename $BUILD_SRC) == "src" ]]; then
|
||||
echo checking in src/ subdirectory for source
|
||||
if [[ ( -d $BUILD_SRC/src/packages && -d $BUILD_SRC/src/init ) ]]; then
|
||||
BUILD_SRC=$BUILD_SRC/src
|
||||
echo found source in src/ subdirectory changing to source directory to
|
||||
echo $BUILD_SRC
|
||||
else
|
||||
echo -e "\e[1;31mERROR: no build source directory at $BUILD_SRC</src>"
|
||||
echo -e "with init/ and packages/ subdirectores was found\e[1;37m"
|
||||
if ! get_build_src; then
|
||||
if [[ $no_prompt ]] ; then
|
||||
echo aborting the build...
|
||||
echo -e "\e[1;31mNOTE: use '_base_' to explicitly use build source in uci-docker-build repo\e[1;37m"
|
||||
echo -e "\e[1;31mNOTE: use '_default_' to explicitly use build source in uci-docker-build repo\e[1;37m"
|
||||
return 2
|
||||
else
|
||||
echo "Do you want to use the uci-docker-build repo source scripts"
|
||||
echo "Do you want to use the uci-docker-build default build source"
|
||||
echo "at $BDIR/src "
|
||||
read -n 1 -p "instead? [y]=>" REPLY
|
||||
[[ $REPLY != "y" ]] && echo -e "\n" && return 2
|
||||
BUILD_SRC=$BDIR/src
|
||||
echo -e "\n\e[1;31mNOTE: use '_base_' to explicitly use build source in uci-docker-build repo\e[1;37m"
|
||||
fi
|
||||
fi
|
||||
echo -e "\n\e[1;31mNOTE: use '_default_' to explicitly use build source in uci-docker-build repo\e[1;37m"
|
||||
fi
|
||||
fi
|
||||
# done processing build source directory
|
||||
|
||||
log_dir=$PWD/logs
|
||||
mkdir -p $log_dir
|
||||
|
||||
pushd "$BDIR" > /dev/null || return 3
|
||||
|
||||
TARGET=${TARGET:-default}
|
||||
[[ ! "${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=$(docker_image_distro $BASE_IMAGE)
|
||||
[[ ! $LINUX_DISTRO ]] && echo "unable to get base image OS for: $BASE_IMAGE, aborting build" && return 5
|
||||
echo $BASE_IMAGE is built from distro $LINUX_DISTRO
|
||||
else
|
||||
BASE_IMAGE=$LINUX_DISTRO
|
||||
fi
|
||||
get_distro
|
||||
|
||||
IMAGE_NAME=$(make_image_name $@)
|
||||
|
||||
|
@ -199,90 +173,83 @@ if [[ $(image_exists $IMAGE_NAME) ]]; then
|
|||
fi
|
||||
|
||||
ARCH=$(get_arch)
|
||||
log_dir=$PWD/logs
|
||||
mkdir -p $log_dir
|
||||
[[ $TARGET == "dev" ]] && VERBOSE=true
|
||||
|
||||
export BASE_IMAGE
|
||||
export TAG
|
||||
export IMAGE_NAME
|
||||
export LINUX_DISTRO
|
||||
export BUILD_SRC
|
||||
export KEEP
|
||||
export SYSADMIN_PW
|
||||
export ARCH
|
||||
export VERBOSE
|
||||
|
||||
echo -e "\e[1;37m********************"
|
||||
echo "Using scripts source directory at $BUILD_SRC"
|
||||
echo "Building with base image: $BASE_IMAGE"
|
||||
#todo based on target form image names
|
||||
echo "Outputing to image name => $IMAGE_NAME<-arch>:${TAG:-latest}"
|
||||
[[ $push || $TARGET == "private" ]] && echo "Will push image to ${REPO:-hub.docker.com}"
|
||||
[[ $TARGET == "deploy" ]] && echo "Will build and push both amd64 and arm64 images to hub.docker.com"
|
||||
[[ $TARGET == "dev" || ! $TARGET ]] && echo "Building image for local machine with architecture $ARCH"
|
||||
echo "Linux Distro: $LINUX_DISTRO"
|
||||
echo "Using build target: ${TARGET:-default}"
|
||||
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 "u********************\e[0;37m"
|
||||
build_info
|
||||
|
||||
if [[ ! $no_prompt ]]; then
|
||||
read -n 1 -p "do you want to continue [y]=>" REPLY
|
||||
[[ $REPLY != "y" ]] && echo -e "\n" && return 4
|
||||
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
|
||||
if ! source $BDIR/Dockerfile.d/create; then
|
||||
echo unable to create Dockerfile from template, aborting build
|
||||
return 3
|
||||
fi
|
||||
|
||||
[[ $TARGET == "private" && ! $REPO ]] && echo "must use '-r <private repo>' if building to private repo" && exit 3
|
||||
builder=default
|
||||
if [[ $TARGET == "publish" ]]; then
|
||||
builder=publish
|
||||
pushd "$BDIR" > /dev/null || return 3
|
||||
if ! docker buildx ls | grep -q publish ; then
|
||||
echo publish builder does not exist, creating with docker-container driver
|
||||
docker buildx create --name publish --driver docker-container >/dev/null
|
||||
docker buildx ls | grep publish
|
||||
fi
|
||||
popd > /dev/null || return 4
|
||||
fi
|
||||
|
||||
# copy source directory to temporary .src/ subdirectory
|
||||
# MUST either be readable by all or group readable by docker group
|
||||
rm -rf $BDIR/.src
|
||||
# copy or bind build source directory to temporary .src/ subdirectory in build repo
|
||||
[[ -d $BDIR/.src ]] && rm -rf $BDIR/.src
|
||||
if [[ $(which rsync 2> /dev/null ) ]]; then
|
||||
rsync -aAru ${BUILD_SRC:-src}/ $BDIR/.src
|
||||
ls -la $BDIR/.src
|
||||
else
|
||||
echo no rsync copying with cp
|
||||
/bin/cp -a ${BUILD_SRC:-src}/. $BDIR/.src > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [[ -f $append_efile ]]; then
|
||||
/bin/cp "$append_efile" "$BDIR/.src/init/env/_build.env_"
|
||||
echo 'source $ENV_DIR/_build.env_' >> $BDIR/.src/init/build.env
|
||||
fi
|
||||
|
||||
pushd "$BDIR" > /dev/null || return 3
|
||||
|
||||
######### RUNNING THE DOCKER BUILD COMMAND ######################
|
||||
echo running build command: docker buildx --builder ${builder} bake ${nocache} ${TARGET}
|
||||
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 5
|
||||
popd > /dev/null || return 4
|
||||
|
||||
rm -rf $BDIR/.src
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
if [[ ($try || $TARGET == "dev") ]] && [[ ! $no_prompt ]]; then
|
||||
if [[ ($TRY_CMD || $TARGET == "dev") ]]; then
|
||||
echo trying newly built image in a container
|
||||
try_container -m opt $([[ $TARGET == "deploy" ]] && echo -p) $IMAGE_NAME
|
||||
echo name before try $IMAGE_NAME
|
||||
try_container build -m opt $([[ $TARGET == "publish" ]] && echo -p) ${TRY_CMD:-shell}
|
||||
fi
|
||||
|
||||
if [[ $TARGET == "private" ]]; then
|
||||
# echo pushing arm64 image $IMAGE_NAME to ${REPO:-docker hub}
|
||||
echo pushing arm64 image $IMAGE_NAME to ${REPO:-docker hub}
|
||||
image_push -a -r $REPO $IMAGE_NAME
|
||||
# echo pushing amd image $IMAGE_NAME to ${REPO:-docker hub}
|
||||
echo pushing amd image $IMAGE_NAME to ${REPO:-docker hub}
|
||||
image_push -r $REPO $IMAGE_NAME
|
||||
else
|
||||
if [[ $push && (! $TARGET == "dev") ]];then
|
||||
# echo pushing $IMAGE_NAME to ${REPO:-docker hub}
|
||||
image_push $([[ $TARGET == "arm" ]] && echo -a) -r $REPO $IMAGE_NAME
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# if script was executed then call the function
|
||||
(return 0 2>/dev/null) || docker_image_build $@
|
||||
(return 0 2>/dev/null) || udbuild "$@"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -14,12 +14,15 @@ variable "BASE_IMAGE" {
|
|||
variable "SYSADMIN_PW" {
|
||||
default = ""
|
||||
}
|
||||
variable "VERBOSE" {
|
||||
default = ""
|
||||
}
|
||||
variable "ARCH" {
|
||||
default = ""
|
||||
}
|
||||
function "tag" {
|
||||
params = [suffix]
|
||||
result = [format("${IMAGE_NAME}%s:${TAG}", notequal("", suffix) ? "-${suffix}" : "")]
|
||||
result = [format("${IMAGE_NAME}%s:${TAG}", notequal("${ARCH}", suffix) ? "-${suffix}" : "")]
|
||||
}
|
||||
# groups
|
||||
group "dev" {
|
||||
|
@ -28,10 +31,7 @@ group "dev" {
|
|||
group "default" {
|
||||
targets = ["${ARCH}"]
|
||||
}
|
||||
group "deploy" {
|
||||
targets = ["multi"]
|
||||
}
|
||||
group "private" {
|
||||
group "multi" {
|
||||
targets = [
|
||||
"amd64",
|
||||
"arm64"
|
||||
|
@ -39,7 +39,7 @@ group "private" {
|
|||
}
|
||||
# intended for use with default local docker builder
|
||||
# uses 'dev' group in docker-bake.hcl
|
||||
# assume dev machine is amd64 machine
|
||||
# assume dev and default build for architecture of local machine
|
||||
target "amd64" {
|
||||
context = "."
|
||||
dockerfile = "Dockerfile"
|
||||
|
@ -47,9 +47,10 @@ target "amd64" {
|
|||
LINUX_DISTRO = "${LINUX_DISTRO}"
|
||||
BASE_IMAGE = "${BASE_IMAGE}"
|
||||
TAG = "${TAG}"
|
||||
VERBOSE = "${VERBOSE}"
|
||||
SYSADMIN_PW = "${SYSADMIN_PW}"
|
||||
}
|
||||
tags = tag("")
|
||||
tags = tag("amd64")
|
||||
platforms = ["linux/amd64"]
|
||||
}
|
||||
|
||||
|
@ -61,28 +62,11 @@ target "arm64" {
|
|||
platforms = ["linux/arm64"]
|
||||
}
|
||||
|
||||
# must use with docker-container driver for multiarch image deployment to registry
|
||||
# uses 'deploy' group in docker-bake.hcl
|
||||
target "multi" {
|
||||
# must use with docker-container driver for multiarch image publishment to registry
|
||||
# uses 'publish' group in docker-bake.hcl
|
||||
target "publish" {
|
||||
inherits = ["amd64"]
|
||||
tags = tag("")
|
||||
tags = ["${IMAGE_NAME}:${TAG}"]
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
output = ["type=registry"]
|
||||
}
|
||||
|
||||
|
||||
// variable "RUSER" {
|
||||
// default = ""
|
||||
// }
|
||||
// function "user" {
|
||||
// params = []
|
||||
// result = [notequal("", RUSER) ? "${RUSER}/" : ""]
|
||||
// }
|
||||
|
||||
// function "tagamd" {
|
||||
// params = []
|
||||
// result = [
|
||||
// format("%s${LINUX_DISTRO}:${TAG}", notequal("", RUSER) ? "${RUSER}/" : ""),
|
||||
// format("%s${LINUX_DISTRO}-amd64:${TAG}", notequal("", RUSER) ? "${RUSER}/" : "")
|
||||
// ]
|
||||
// }
|
|
@ -1,6 +0,0 @@
|
|||
SYSADMIN_PW=ucommandit
|
||||
# default is alpine
|
||||
# LINUX_DISTRO=alpine
|
||||
RUSER=ucommandit
|
||||
# TARGET=deploy
|
||||
BUILD_SRC=../src
|
|
@ -1,13 +0,0 @@
|
|||
#!/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 "$@"
|
|
@ -0,0 +1,3 @@
|
|||
# invokes try with the example environment file
|
||||
# assumes image already built
|
||||
udbuild -e example.env "$@"
|
|
@ -1 +0,0 @@
|
|||
dbuild -e example.env "$@"
|
|
@ -1,17 +1,20 @@
|
|||
|
||||
# for easy use copy this file to .env and it will be sourced
|
||||
# otherwise invoke `udbuild -e example.env`
|
||||
# using a filename of just .env will load it by default
|
||||
# LINUX_DISTRO ignored if BASE_IMAGE is set
|
||||
LINUX_DISTRO=alpine
|
||||
# LINUX_DISTRO=alpine
|
||||
# BASE_IMAGE="dockerhubuser/mybase"
|
||||
# tag is 'latest' by default
|
||||
# TAG=1.0.0
|
||||
# will be prepended to image name with /, used mostly for deploying
|
||||
RUSER=dockerhubuser
|
||||
# will be prepended to image name with /, used mostly for publishing
|
||||
RUSER=testing
|
||||
# default is hub.docker.com
|
||||
# REPO=my.priviate.repo.net
|
||||
# if using base source this will set the pw for the sysadmin user in the image
|
||||
SYSADMIN_PW=ucommandit
|
||||
# default target is dev
|
||||
# TARGET=deploy
|
||||
# default target is "default"
|
||||
# TARGET=publish
|
||||
BUILD_SRC=../src
|
||||
# looks for /init and /packages in present directory by default
|
||||
# also looks in src/ subdirectory
|
||||
|
@ -19,9 +22,6 @@ BUILD_SRC=../src
|
|||
# use '_base_' to force using the uci-docker-build build source
|
||||
# BUILD_SRC=._base_
|
||||
# in the image where the build scripts are put /build by default
|
||||
# BUILD_DIR=/opt/build
|
||||
# keep the build scripts in the image. default is to remove them after build
|
||||
# KEEP=true
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# this would push build image to a custome git server that supports packages like gitea
|
||||
# LINUX_DISTRO=alpine
|
||||
RUSER=ucommandit
|
||||
TARGET=private
|
||||
REPO=git.mygitserver.net
|
||||
BUILD_SRC=../src
|
|
@ -0,0 +1,5 @@
|
|||
# LINUX_DISTRO=alpine
|
||||
# this will publish both arm and amd version to docker hub
|
||||
RUSER=ucommandit
|
||||
TARGET=publish
|
||||
BUILD_SRC=../src
|
|
@ -0,0 +1,2 @@
|
|||
# invokes build with the example environment file
|
||||
udbuild try -e example.env ${@:-shell}
|
23
install
23
install
|
@ -11,7 +11,12 @@ 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 $target; then
|
||||
if [[ -f $target ]]; then
|
||||
echo "$target already exists do you want to overwrite? (y/n) "
|
||||
read -e ans
|
||||
[[ ! $ans == "y" ]] && exit 1
|
||||
fi
|
||||
if ln -fns $builder/build $target; then
|
||||
[[ ! $(command -v $cmd) ]] && echo FATAL: link failed $cmd not found in path \
|
||||
|| echo install success: try \'$cmd -h\' now
|
||||
else
|
||||
|
@ -19,11 +24,13 @@ if [[ $found ]]; then
|
|||
echo if \': Permission denied\' 'then' run \'sudo ./install\'
|
||||
fi
|
||||
else
|
||||
echo $parent not in current path
|
||||
echo "Install failed: $parent not in current path"
|
||||
echo $PATH
|
||||
echo link to script not created
|
||||
echo "add the following export somewhere in your shell (e.g. ~/.bashrc)"
|
||||
echo "export UDBUILD=$builder/build"
|
||||
echo 'and then use $UDBUILD to invoke the build script ( e.g $UDBUILD -e mybuild.env)'
|
||||
echo "or rerun this script using a directory in the system path (e.g ./install /usr/bin build)"
|
||||
fi
|
||||
echo "link to script not created. your install options are:"
|
||||
echo "1. add $parent to your PATH"
|
||||
echo "2. rerun this script using a directory in the system path (e.g ./install /usr/bin build)"
|
||||
echo "3. add the following export somewhere in your shell (e.g. ~/.bashrc)"
|
||||
echo " export UDBUILD=$builder/build"
|
||||
echo ' and then use $UDBUILD to invoke the build script'
|
||||
echo ' ( e.g $UDBUILD -e Smybuild.env)'
|
||||
fi
|
File diff suppressed because it is too large
Load Diff
|
@ -1,68 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
image_name () {
|
||||
|
||||
local tag; local efile
|
||||
|
||||
# generate a full image name with tag
|
||||
# $1 name, $2 user(or repo), $3 repo
|
||||
|
||||
# [[ $# -lt 1 ]] && echo "image base name required" && exit
|
||||
|
||||
declare OPTION; declare OPTARG; declare OPTIND
|
||||
while getopts 'e:ag:r:u:' OPTION; do
|
||||
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
|
||||
case "$OPTION" in
|
||||
e)
|
||||
efile=$OPTARG
|
||||
;;
|
||||
r)
|
||||
REPO=$OPTARG
|
||||
;;
|
||||
u)
|
||||
RUSER=$OPTARG
|
||||
;;
|
||||
g)
|
||||
TAG=$OPTARG
|
||||
;;
|
||||
a) # add -arm64 to image
|
||||
arm=arm64
|
||||
;;
|
||||
*) echo unknown run option -$OPTARG
|
||||
echo "USAGE: tag <options>"
|
||||
echo "available options: -a add -arm64 to tag, -d delete tag "
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
echo $efile
|
||||
if [[ $efile ]]; then
|
||||
[[ ! -f $efile ]] && efile=$SDIR/$efile
|
||||
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 "----------"
|
||||
fi
|
||||
|
||||
tag=$( echo $1 | cut -s -d ":" -f2)
|
||||
tag=${tag:-$TAG}
|
||||
name=${1%:*}
|
||||
user=${2:-$RUSER}
|
||||
repo=${3:-$REPO}
|
||||
|
||||
tag=$([[ $repo ]] && echo ${repo}/)$([[ $user ]] && echo ${user}/)$name$([[ $arm ]] && echo -arm64):${TAG:-latest}
|
||||
|
||||
echo $tag
|
||||
|
||||
}
|
||||
|
||||
# if script was executed then call the function
|
||||
(return 0 2>/dev/null) || image_name $@
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
|
||||
image_name () {
|
||||
|
||||
local tag; local efile; local suffix
|
||||
|
||||
# generate a full image name with tag
|
||||
# $1 name, $2 user(or repo), $3 repo
|
||||
|
||||
# [[ $# -lt 1 ]] && echo "image base name required" && exit
|
||||
|
||||
declare OPTION; declare OPTARG; declare OPTIND
|
||||
while getopts 'e:s:g:r:u:' OPTION; do
|
||||
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
|
||||
case "$OPTION" in
|
||||
e)
|
||||
efile=$OPTARG
|
||||
;;
|
||||
u)
|
||||
RUSER=$OPTARG
|
||||
;;
|
||||
g)
|
||||
TAG=$OPTARG
|
||||
;;
|
||||
s) # add -arm64 to image
|
||||
suffix=$OPTARG
|
||||
;;
|
||||
*) echo unknown image-name option -$OPTARG
|
||||
echo "USAGE: image_name <options> <name> <repo_user>"
|
||||
echo "available options: -s <suffix>: add -<suffix> , -g: tag, -u: repo user, -e: env file"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
|
||||
source_env_file $efile
|
||||
|
||||
tag=$( echo $1 | cut -s -d ":" -f2)
|
||||
TAG=${tag:-$TAG}
|
||||
name=${1%:*}
|
||||
shift
|
||||
|
||||
get_distro
|
||||
echo $(make_image_name $name $@)$([[ $suffix ]] && echo -$suffix):${TAG:-latest}
|
||||
}
|
||||
|
||||
# if script was executed then call the function
|
||||
(return 0 2>/dev/null) || image_name $@
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
# UCOMMANDIT DOCKER BUILD SCRIPT
|
||||
|
||||
Image Build Script: Creates one or more images using a target per the docker-bake.hcl file
|
||||
|
||||
## USAGE
|
||||
|
||||
`udbuild <option switches> <image_name> <repo_user>`
|
||||
|
||||
image_name and repo_name are optional and can also be set by environments NAME and RUSER.
|
||||
RUSER can also be set by -u option if image_name is not provided.
|
||||
|
||||
`udbuild <subcommand> <subcommand option switches> <subcommand arguments>`
|
||||
|
||||
## SUBCOMMANDS:
|
||||
|
||||
`try` - runs a trial container with image
|
||||
|
||||
`load_env_file <path>` - loads an build environment file, useful aid for an external script
|
||||
|
||||
`build_src <path>` - attempts to locate a valid build source directory
|
||||
|
||||
`help,-help,--help <subcommand>` - view this info or that of a subcommand
|
||||
|
||||
`source` - view the source of this script
|
||||
|
||||
`image` - image related subcommands
|
||||
* `name` - generate name from environment/switches
|
||||
* `tag` - add a name (docker tag) to an existing image
|
||||
* `push` - push an image to a remote repository
|
||||
* `delete` - completely delete a local image
|
||||
* `info` - with no subcommand show all info for image
|
||||
- `arch` - list machine architecture of image
|
||||
- `exists` - used mostly for scripting, determines if image exists locally
|
||||
- `tags` - get the names (docker tags) of an image
|
||||
-S `id` - gets the id of an image from its name (docker tag)
|
||||
|
||||
## BUILD OPTIONS
|
||||
|
||||
### setable ONLY via CLI switches
|
||||
|
||||
`-h` show this help
|
||||
|
||||
`-p` if running interactive suppress the build prompts
|
||||
|
||||
`-n` use no-cache, bust the cache and force rebuild the entire image, see `-f:REBUILD`
|
||||
|
||||
`-o` do not overwrite an existing image on build (default), instead move it to a temporary timestamp tag
|
||||
|
||||
### setable via CLI switches or via environment variable
|
||||
|
||||
`-v : VERBOSE=true` - show verbose information about the build, verbose is default for `dev` target
|
||||
|
||||
`-a <path> : APPEND_BUILD_ENV=<path>`- append this environment file to baked in build.env for image. Allows easy customizing of image build environment found at src/init/build.env
|
||||
|
||||
`-l : APPEND_DISTRO=true` - will append the distro name to the image name. Can help to identify different distros when making distro variation of the same build
|
||||
|
||||
`-g <tag> : TAG=<tag>` - tag following : in output image name (i.e. REPO/USER/NAME:TAG), default: latest
|
||||
|
||||
`-e <path> : BUILD_EFILE=<path>` - source an environment file. By default will look for .env, in PWD. If used will also try <path> and <path>.env in PWD.
|
||||
|
||||
`-d : LINUX_DISTRO=<name>` - supported: alpine, debian, ubuntu, default: alpine; if base image set distro will be determined (and this ignored). Default is alpine
|
||||
|
||||
`-i <path> : IMAGE_INFO=<path>` - path to file of information to be included in the image at `/opt/image.info` and visible via `image` command of the entrypoint. Will over write any image.ifo file in src/init/image.info of the build sources
|
||||
|
||||
`-a <path> : APPEND_EFILE=<path>` - will include this file in build source and source it during the init RUN. So a way to set custom build environment without editing the build source.
|
||||
|
||||
`-b <name> : BASE_IMAGE=<name>` - used in `FROM` in Dockerfile. The default will be an official distro image (e.g.`ubuntu:latest`) based on `LINUX_DISTRO` and the default distro is alpine so if both `BASE_IMAGE` and `LINUX_DISTRO` are unset FROM will use `alpine:latest`
|
||||
|
||||
`-t <target> : TARGET=<target>` - the valid build targets for `buildx bake` are `dev arm64 amd64 publish multi default` default is `default`
|
||||
|
||||
`-r <repo> : REPO=<repo>` - set a remote private repository for pushing, default is docker hub
|
||||
|
||||
`-c <cmd> : TRY_CMD=<cmd>` - a command to use in the try container, default is 'shell`
|
||||
|
||||
`-s <path> : BUILD_SRC=<path>` - set the path to the build source directory, default is src/ in current or parent directory`
|
||||
|
||||
`-f : REBUILD=init` - force rebuild of only the Dockerfile RUN initialize instruction, note: use `-n` to force rebuild of entire image
|
||||
|
||||
`-u <name> : RUSER=<name>` - the remote repository user name to prepend to the image name. This will be needed for pushing to remote repositories like docker hub or a private repository (e.g. gitea)
|
||||
|
||||
### setable ONLY via environment variable
|
||||
|
||||
|
||||
## examples:
|
||||
|
||||
### commad line
|
||||
|
||||
### environment file
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
image_tag () {
|
||||
|
||||
local name; local remove; local id
|
||||
|
||||
# tags an image
|
||||
# -i <imagetag or id> <newimagetag>
|
||||
|
||||
[[ $# -lt 1 ]] && echo "image base name required" && exit
|
||||
[[ $1 == "-r" ]] && remove=true && shift 1
|
||||
[[ $1 == "-i" ]] && { shift 1; id=$1; } || id=$(image_id $1)
|
||||
name=$(image_name "$1")
|
||||
[[ ! $id ]] && { echo "no image with id:$id name:$name"; return 1; }
|
||||
|
||||
if [[ $2 ]];then
|
||||
# echo making tag for $2 $(image_name $2)
|
||||
docker tag $id $(image_name $2)
|
||||
else
|
||||
[[ $remove ]] && docker rmi $name || echo to remove an image tag use -r
|
||||
fi
|
||||
image_tags $id
|
||||
}
|
||||
|
||||
image_delete () {
|
||||
docker rmi -f "$@"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
|
||||
image_tag () {
|
||||
|
||||
local name; local remove; local id; local ntag; local tag
|
||||
|
||||
# tags an image
|
||||
# -i <imagetag or id> <newimagetag>
|
||||
[[ $1 == "-r" ]] && remove=true && shift 1
|
||||
if [[ $1 == "-i" ]]; then
|
||||
shift 1
|
||||
id=$1
|
||||
else
|
||||
id=$(image_id $1)
|
||||
name=$1
|
||||
fi
|
||||
[[ ! $(image_exists $id) ]] && { echo "no image $name $id nothing to tag"; return 1; }
|
||||
ntag=$2
|
||||
if [[ $ntag ]];then
|
||||
# echo making tag for $2 $(image_name $2)
|
||||
[[ $ntag = :* ]] && ntag=$( echo $name | cut -d ":" -f1)$ntag
|
||||
docker tag $id $ntag
|
||||
else
|
||||
[[ $remove ]] && docker rmi $name || echo to remove an image tag use -r
|
||||
fi
|
||||
image_tags $id
|
||||
}
|
||||
|
||||
image_delete () {
|
||||
local id
|
||||
id=$(image_id $@)
|
||||
docker rmi -f $id
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
150
lib/cmds/try
150
lib/cmds/try
|
@ -1,150 +0,0 @@
|
|||
#!/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")
|
||||
local mp;local cuser; local hmp; local vname; local prod; local priv
|
||||
local hostmp; local efile; local entrypoint; local evar
|
||||
local envf; local image; local append_distro; local options
|
||||
|
||||
declare OPTION; declare OPTARG; declare OPTIND
|
||||
OPTIND=0
|
||||
while getopts 'lf:o:dpr:t:u:m:h:kv:e:s:' OPTION; do
|
||||
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
|
||||
case "$OPTION" in
|
||||
s)
|
||||
entrypoint="--entrypoint $OPTARG"
|
||||
;;
|
||||
e)
|
||||
if ! source_env_file $OPTARG; then return 2; fi
|
||||
efile=true
|
||||
;;
|
||||
f)
|
||||
envf="--env-file $OPTARG"
|
||||
;;
|
||||
d)
|
||||
dryrun="echo "
|
||||
;;
|
||||
u)
|
||||
cuser=$OPTARG
|
||||
;;
|
||||
l)
|
||||
# append distro name to image name
|
||||
append_distro=true
|
||||
;;
|
||||
k)
|
||||
keep=true
|
||||
;;
|
||||
# s)
|
||||
# save=true
|
||||
# ;;
|
||||
m)
|
||||
mp=$OPTARG
|
||||
;;
|
||||
o)
|
||||
options=$OPTARG
|
||||
;;
|
||||
h)
|
||||
hmp=$OPTARG
|
||||
;;
|
||||
v)
|
||||
evar="-e $OPTARG"
|
||||
;;
|
||||
t)
|
||||
TAG=$OPTARG
|
||||
;;
|
||||
p)
|
||||
priv=--privileged
|
||||
;;
|
||||
r)
|
||||
prod=$OPTARG
|
||||
;;
|
||||
*) echo unknown run option -$OPTARG
|
||||
echo "USAGE: try <options>"
|
||||
echo "available options: -t <latest> custom tag "
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
[[ ! $efile ]] && source_env_file
|
||||
|
||||
image=$(make_image_name $@)
|
||||
|
||||
echo image name to try: $image
|
||||
|
||||
[[ ! $image ]] && echo must supply an image to try && return 1
|
||||
|
||||
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}
|
||||
|
||||
docker rm try-$name > /dev/null 2>&1
|
||||
if [[ $mp ]]; then
|
||||
hostmp="${hmp:-${PWD}/mnt/$mp}"
|
||||
[[ ! $(isAbsPath $hostmp) ]] && hostmp=$PWD/$hostmp
|
||||
vname="try-$name${dir//\//-}"
|
||||
mkdir -p "$hostmp"
|
||||
# echo bind $dir to volume $vname
|
||||
$dryrun docker volume create --driver local \
|
||||
--opt type=none \
|
||||
--opt device=$hostmp \
|
||||
--opt o=bind "$vname" > /dev/null
|
||||
[[ ! $dryrun ]] && echo directory $mp in container will be mounted at $hostmp
|
||||
# else
|
||||
# vname="try-$name-${mp//\//-}"
|
||||
# hostmap="-e HOST_MAP=$(id -u):$(id -g)"
|
||||
# dkpath=$(docker info | grep -i "Docker Root Dir" | cut -d':' -f2)/volumes/$vname/_data
|
||||
# echo via volume $vname
|
||||
# echo linking $dkpath to $hostmp
|
||||
# $dryrun ln -s $dkpath -T $hostmp
|
||||
# fi
|
||||
fi
|
||||
|
||||
echo starting container with image: $image, and name $name
|
||||
echo at container prompt type \'exit\' to exit from shell and remove trial container
|
||||
# --entrypoint /opt/scripts/entrypoint.sh \
|
||||
$dryrun docker run -i -t --rm $priv $evar $options \
|
||||
${entrypoint} ${evnf} \
|
||||
$([[ $cuser ]] && echo "--user $cuser") \
|
||||
--name try-$name --hostname try-$host-$name \
|
||||
$([[ $mp ]] && echo "-v $vname:/$mp") \
|
||||
"$image" \
|
||||
"$@"
|
||||
echo "done with session, removing containter try-$name"
|
||||
if [[ $mp ]] && [[ ! $dryrun ]]; then
|
||||
# if [[ ! $save ]]; then
|
||||
echo removing volume $vname used for mapping
|
||||
docker volume rm $vname > /dev/null
|
||||
if [[ $keep ]]; then
|
||||
echo mounted container directory $mp on host at $hostmp will not be removed
|
||||
else
|
||||
echo deleting directory at mountpoint $hostmp mapped to $mp in container
|
||||
echo "use option -k to keep this directory after exiting container"
|
||||
echo "useful for testing scripts inside the container"
|
||||
rm -rf $hostmp
|
||||
fi
|
||||
# [[ ! $bind ]] && [[ -h $hostmp ]] && echo "removing link at $hostmp" && rm $hostmp
|
||||
# fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# if script was executed then call the function
|
||||
(return 0 2>/dev/null) || try_container "$@"
|
|
@ -0,0 +1,181 @@
|
|||
#!/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 published to docker image
|
||||
|
||||
try_container () {
|
||||
|
||||
declare -A arch=( ["x86_64"]="" ["aarch64"]="-arm64")
|
||||
local mp;local cuser; local hmp; local vname; local prod; local priv
|
||||
local hostmp; local efile; local entrypoint; local evar
|
||||
local envf; local image; local options; local dry_run
|
||||
local build; local cmd; local script; local dcmd
|
||||
|
||||
[[ $1 == "build" ]] && build=true && shift
|
||||
|
||||
declare OPTION; declare OPTARG; declare OPTIND
|
||||
OPTIND=0
|
||||
while getopts "f:o:dpr:t:u:m:h:kv:e:i:c:s:b:y:" OPTION; do
|
||||
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
|
||||
case "$OPTION" in
|
||||
y)
|
||||
entrypoint="--entrypoint $OPTARG"
|
||||
;;
|
||||
s)
|
||||
script="$OPTARG"
|
||||
;;
|
||||
e)
|
||||
efile=$OPTARG
|
||||
;;
|
||||
c)
|
||||
cmd=$OPTARG
|
||||
;;
|
||||
i)
|
||||
image="$OPTARG"
|
||||
;;
|
||||
f)
|
||||
envf="--env-file $OPTARG"
|
||||
;;
|
||||
b)
|
||||
# CUSTOM BASE IMAGE
|
||||
BASE_IMAGE=$OPTARG
|
||||
;;
|
||||
d)
|
||||
dry_run="echo "
|
||||
;;
|
||||
u)
|
||||
cuser=$OPTARG
|
||||
;;
|
||||
k)
|
||||
keep=true
|
||||
;;
|
||||
m)
|
||||
mp=$OPTARG
|
||||
;;
|
||||
o)
|
||||
options=$OPTARG
|
||||
;;
|
||||
h)
|
||||
hmp=$OPTARG
|
||||
;;
|
||||
v)
|
||||
evar="-e $OPTARG"
|
||||
;;
|
||||
t)
|
||||
TAG=$OPTARG
|
||||
;;
|
||||
p)
|
||||
priv=--privileged
|
||||
;;
|
||||
r)
|
||||
prod=$OPTARG
|
||||
;;
|
||||
*) echo unknown run option -$OPTARG
|
||||
echo "USAGE: try <options>"
|
||||
echo "available options: -t <latest> custom tag "
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
image=${image:-$IMAGE_NAME}
|
||||
|
||||
if [[ ! ( $build && $image ) ]]; then
|
||||
echo attempting to getting image name from environment file
|
||||
get_distro
|
||||
source_env_file $efile
|
||||
image=$(make_image_name)
|
||||
fi
|
||||
|
||||
if [[ ! $image ]]; then
|
||||
echo must supply an image name to try either via -i option
|
||||
echo or setting $IMAGE_NAME environment variable
|
||||
echo or from an environment file
|
||||
return 1
|
||||
fi
|
||||
|
||||
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}
|
||||
|
||||
echo trying image name: $image
|
||||
|
||||
docker rm try-$name > /dev/null 2>&1
|
||||
if [[ $mp ]]; then
|
||||
hostmp="${hmp:-${PWD}/mnt/$mp}"
|
||||
[[ ! $(isAbsPath $hostmp) ]] && hostmp=$PWD/$hostmp
|
||||
vname="try-$name${dir//\//-}"
|
||||
echo $vname
|
||||
mkdir -p "$hostmp"
|
||||
dvcmd=$( tr "\n" " " <<-END
|
||||
docker volume create --driver local
|
||||
--opt type=none
|
||||
--opt device=$hostmp
|
||||
--opt o=bind $vname
|
||||
END
|
||||
)
|
||||
if [[ $dry_run ]]; then
|
||||
echo dry run volume creation command
|
||||
echo $dvcmd
|
||||
else
|
||||
if ! $dvcmd > /dev/null; then
|
||||
echo error creating volume, aborting container try
|
||||
return 4
|
||||
fi
|
||||
fi
|
||||
echo directory $mp in container will be mounted at $hostmp
|
||||
fi
|
||||
|
||||
if [[ ! $dry_run ]]; then
|
||||
echo starting container with image: $image, and name $name
|
||||
echo at container prompt type \'exit\' to exit from shell and remove trial container
|
||||
fi
|
||||
dcmd=$( tr "\n" " " <<-END
|
||||
docker run -i $([[ ! $script ]] && echo -t)
|
||||
--rm $priv $evar $options ${entrypoint} ${evnf}
|
||||
$([[ $cuser ]] && echo --user $cuser)
|
||||
--name try-$name --hostname try-$host-$name
|
||||
$([[ $mp ]] && echo -v $vname:/$mp)
|
||||
$image
|
||||
$([[ $script ]] && echo script || ${cmd} ) $@
|
||||
END
|
||||
)
|
||||
if [[ $dry_run ]]; then
|
||||
echo dry run, docker command
|
||||
echo "$([[ -f $script ]] && echo cat || echo "echo") "$script" | $dcmd"
|
||||
elif [[ $script ]]; then
|
||||
$([[ -f $script ]] && echo cat || echo "echo") "$script" | $dcmd
|
||||
else
|
||||
$dcmd
|
||||
echo "done with session, removing containter try-$name"
|
||||
if [[ $mp ]] ; then
|
||||
echo removing volume $vname used for mapping
|
||||
docker volume rm $vname > /dev/null
|
||||
if [[ $keep ]]; then
|
||||
echo mounted container directory $mp on host at $hostmp will not be removed
|
||||
else
|
||||
echo deleting directory at mountpoint $hostmp mapped to $mp in container
|
||||
echo "use option -k to keep this directory after exiting container"
|
||||
echo "useful for testing scripts inside the container"
|
||||
rm -rf $hostmp
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# if script was executed then call the function
|
||||
(return 0 2>/dev/null) || try_container "$@"
|
|
@ -1,34 +0,0 @@
|
|||
#!/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 <subcommand> <options> <build_target> <imagename, imageuser>"
|
||||
echo "valid build_target: ${targets[*]}; default: dev"
|
||||
echo "### subcommands:"
|
||||
echo "try (runs try a container script, see try usage) $0 try -i"
|
||||
echo "tag (runs image_tag script)"
|
||||
echo "info get image info, info <arch, exists, id> nothing is all info in json"
|
||||
echo "--- option switches (no argument):"
|
||||
echo "-o do not overwrite an existing image (default), instead move it to a temporary timestamp tag"
|
||||
echo "-i rebuild only the initialization RUN by busting the cache at that point"
|
||||
echo "-v show verbose information about the build"
|
||||
echo "-a (auto) do not prompt to continue build, by default will not prompt if non-interactive shell"
|
||||
echo "-c after build 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 "-k keep the build scripts (see -w) after the build so they are incorporated into the image"
|
||||
echo "-p push to repository; after build push to repository default is hub.docker.com (not need for deploy target)"
|
||||
echo "--- options with argument <ARGUMENT>:"
|
||||
echo "-e <path to environment file> load any or all of options below via a file"
|
||||
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 <BUILD_DIR>; set a custom WORKDIR in Dockerfile (in image), default is /build, see -k"
|
||||
echo "--- options set ONLY by environment variable (see -e as well)"
|
||||
echo "<SYSADMIN_PW> set alternate password for container sysadmin account, default is 'sysadmin'"
|
||||
echo "NOTE any option with <CAPTIALIZED> above can be set in environment instead"
|
||||
echo "#### examples:"
|
||||
echo "$0 -a -d ubuntu -u ucommandit"
|
||||
echo "build (without prompt) a local ubuntu image from scratch and label it ucommandit/ubuntu:latest"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
usage() {
|
||||
|
||||
local help; local force
|
||||
help=$(dirname "$(realpath "$BASH_SOURCE")")/help.md
|
||||
[[ $1 == "c" ]] && force=cat
|
||||
if [[ $(which glow) && ! $force ]]; then
|
||||
glow $help
|
||||
else
|
||||
echo -e "\e[1;31mfor a better experience viewing this help file install glow, https://github.com/charmbracelet/glow\e[1;37m"
|
||||
sed 's/`//g' < $help
|
||||
fi
|
||||
|
||||
}
|
174
lib/helpers.lib
174
lib/helpers.lib
|
@ -1,5 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
quiet () {
|
||||
if [[ $VERBOSE ]]; then $@; fi
|
||||
}
|
||||
|
||||
get_arch () {
|
||||
local arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
|
@ -34,14 +38,15 @@ sed_ignore_comments () {
|
|||
}
|
||||
|
||||
clean_env_file () {
|
||||
local compact
|
||||
local compact; local lines
|
||||
# -c will also remove comments and all empty lines
|
||||
[[ $1 == "-c" ]] && compact=true && shift 1
|
||||
#
|
||||
# remove trailing spaces | remove double quotes
|
||||
# | remove blanks after equals and quote value | remove any spaces before afer =
|
||||
# remove blank lines | remove comment lines if requested
|
||||
cat $1 | sed_ignore_comments s/\\s*$//g | sed_ignore_comments s/\"//g \
|
||||
[[ -f $1 ]] && lines=$(<$1) || lines="$1"
|
||||
echo "$lines" | sed_ignore_comments s/\\s*$//g | sed_ignore_comments s/\"//g \
|
||||
| sed_ignore_comments s/\(=[[:blank:]]*\)\(.*\)/\\1\"\\2\"/ \
|
||||
| sed_ignore_comments s/\\s*=\\s*/=/g \
|
||||
| sed -rz 's/^\n+//; s/\n+$/\n/g' | if [[ $compact ]]; then grep -v '^#' | grep -v "^$" ; else cat; fi
|
||||
|
@ -62,48 +67,50 @@ read_env_file() {
|
|||
if [[ ! ${!evar} ]]; then
|
||||
# echo DECLARE $evar via $line
|
||||
if declare -gx "$(echo "${line}" | sed 's/\"//g' )"; then
|
||||
echo loaded: ${evar}=${!evar}
|
||||
quiet echo loaded: ${evar}=${!evar}
|
||||
else
|
||||
echo error setting $evar
|
||||
quiet echo error setting $evar
|
||||
return 1
|
||||
|
||||
fi
|
||||
else
|
||||
echo $evar already set to ${!evar}
|
||||
quiet echo $evar already set to ${!evar}
|
||||
fi
|
||||
done < <(clean_env_file -c $1)
|
||||
}
|
||||
|
||||
source_env_file () {
|
||||
local default; local efile
|
||||
if efile=$(env_file $1); then
|
||||
local default;local efile
|
||||
if efile=$(env_file ${1:-$BUILD_EFILE}); then
|
||||
[[ $efile == ".env" ]] && default=true
|
||||
[[ ! $(isAbsPath $efile) ]] && efile=$(realpath $efile)
|
||||
echo -e "\e[1;37m********************\e[0;37m"
|
||||
echo loading build environment with environment file
|
||||
echo $efile
|
||||
echo ----------------
|
||||
cat $efile
|
||||
echo ----------------
|
||||
quiet echo -e "\e[1;37m********************\e[0;37m"
|
||||
quiet echo loading build environment with environment file
|
||||
quiet echo $efile
|
||||
quiet echo ----------------
|
||||
quiet cat $efile
|
||||
quiet echo ----------------
|
||||
if read_env_file "$efile"; then
|
||||
[[ $default ]] && echo -e "\e[1;31mNOTE: sourced default .env file in present directory\e[0;37m"
|
||||
echo -e "\e[1;37m********************\e[0;37m"
|
||||
[[ $default ]] && quiet echo -e "\e[1;31mNOTE: sourced default .env file in present directory\e[0;37m"
|
||||
quiet echo -e "\e[1;37m********************\e[0;37m"
|
||||
BUILD_EFILE=$efile
|
||||
else
|
||||
echo error occured while loading environment file
|
||||
echo $efile
|
||||
echo exiting
|
||||
echo -e "\e[1;37m********************\e[0;37m"
|
||||
quiet echo error occured while loading environment file
|
||||
quiet echo $efile
|
||||
quiet echo exiting
|
||||
quiet echo -e "\e[1;37m********************\e[0;37m"
|
||||
return 2
|
||||
fi
|
||||
else
|
||||
if [[ $efile ]]; then
|
||||
echo unable to find an environment file with passed ${1}
|
||||
quiet echo unable to find an environment file with passed ${1}
|
||||
else
|
||||
echo unable to find default environment file .env
|
||||
echo using passed and default build options
|
||||
quiet echo unable to find default environment file .env
|
||||
quiet echo using the current environment plus default build options
|
||||
fi
|
||||
return 2
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
docker_image_distro() {
|
||||
|
@ -115,10 +122,27 @@ echo $(cat $temp | tr [:upper:] [:lower:] | grep -Poi '(debian|ubuntu|red hat|ce
|
|||
rm $temp
|
||||
}
|
||||
|
||||
get_distro() {
|
||||
|
||||
LINUX_DISTRO=${LINUX_DISTRO:-alpine}
|
||||
|
||||
if [[ $BASE_IMAGE ]]; then
|
||||
quiet echo determining DISTRO of base image: $BASE_IMAGE
|
||||
LINUX_DISTRO=$(docker_image_distro $BASE_IMAGE)
|
||||
[[ ! $LINUX_DISTRO ]] && quiet echo "unable to get base image OS for: $BASE_IMAGE, aborting build" && return 5
|
||||
quiet echo $BASE_IMAGE is built from distro $LINUX_DISTRO
|
||||
else
|
||||
BASE_IMAGE=$LINUX_DISTRO
|
||||
fi
|
||||
}
|
||||
|
||||
make_image_name () {
|
||||
|
||||
local arch
|
||||
|
||||
# echo making image name $@
|
||||
# echo name: $NAME
|
||||
# echo APPEND: $APPEND_DISTRO
|
||||
# echo user: $RUSER
|
||||
# echo distro $LINUX_DISTRO
|
||||
|
||||
|
@ -131,12 +155,114 @@ if [[ $2 ]]; then
|
|||
RUSER=$2
|
||||
fi
|
||||
if [[ $NAME ]]; then
|
||||
[[ $append_distro ]] && NAME=$NAME-${LINUX_DISTRO}
|
||||
[[ $APPEND_DISTRO ]] && NAME=$NAME-${LINUX_DISTRO}
|
||||
else
|
||||
# echo no image name supplied using distro name ${LINUX_DISTRO:-alpine}
|
||||
NAME=${LINUX_DISTRO:-alpine}
|
||||
fi
|
||||
|
||||
echo $([[ $RUSER ]] && echo ${RUSER}/)${NAME}
|
||||
[[ $TARGET == "arm64" && ! $TARGET == $(get_arch) ]] && arch=-$TARGET
|
||||
[[ $TARGET == "amd64" && ! $TARGET == $(get_arch) ]] && arch=-$TARGET
|
||||
|
||||
echo $([[ $RUSER ]] && echo ${RUSER}/)${NAME}$arch
|
||||
|
||||
}
|
||||
|
||||
get_build_src () {
|
||||
# processing the build source directory
|
||||
local src; local spath; local spaths
|
||||
check_dir () {
|
||||
[[ ( -d $1/packages && -d $1/init ) ]] || return 1
|
||||
}
|
||||
|
||||
src=${1:-$BUILD_SRC}
|
||||
[[ $src == "_default_" ]] && src=${BDIR}/src
|
||||
src=${src:-src}
|
||||
unset BUILD_SRC
|
||||
|
||||
if check_dir $src; then
|
||||
BUILD_SRC=$(realpath $src)
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo build source path \'$src\' not initially found
|
||||
echo looking in parent directories for a valid build source directory
|
||||
echo to avoid this search use BUILD_SRC= in an environment file
|
||||
spaths="$PWD $(dirname $PWD)/$src $(dirname $PWD)"
|
||||
for spath in $spaths; do
|
||||
echo checking for source in: $spath
|
||||
if check_dir $spath; then
|
||||
echo found valid source directory!
|
||||
echo using $spath
|
||||
BUILD_SRC=$spath
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\e[1;31mERROR: unable to find a build source directory as $src \e[1;37m"
|
||||
return 1
|
||||
}
|
||||
|
||||
build_info () {
|
||||
|
||||
|
||||
echo "Build Command: docker buildx --builder ${builder} bake ${nocache} ${TARGET}"
|
||||
if [[ $VERBOSE ]]; then
|
||||
echo -e "\n!!!!!!!!!!!!!!!!EXTRA BUILD INFO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
pushd "$BDIR" > /dev/null || return 3
|
||||
docker buildx bake --print $TARGET
|
||||
popd > /dev/null || return 4
|
||||
echo -e "\n---------------------------------"
|
||||
echo "build source at $BUILD_SRC to be mounted to /build in container ***** "
|
||||
ls -la $BUILD_SRC
|
||||
echo -e "\n----- base init script init.sh ------"
|
||||
cat $BUILD_SRC/init/init.sh
|
||||
echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
fi
|
||||
|
||||
echo -e "\e[1;37m**************BUILD PARAMETERS *******************************"
|
||||
echo "Architecture of this machine doing the building: $ARCH"
|
||||
echo "Using scripts source directory at $BUILD_SRC"
|
||||
echo "Building with base image: $BASE_IMAGE"
|
||||
echo "Build logs can be found in directory $log_dir"
|
||||
echo "Linux Distro of Image: $LINUX_DISTRO"
|
||||
echo "Using build target: ${TARGET}"
|
||||
echo "----- output --------"
|
||||
echo creating image
|
||||
case $TARGET in
|
||||
|
||||
multi)
|
||||
echo "names for both amd64 and arm64, image without architecture suffix is $ARCH"
|
||||
echo -e "\e[1;31m$IMAGE_NAME$([[ ! $ARCH == amd64 ]] && echo -amd64):${TAG:-latest}\n$IMAGE_NAME$([[ ! $ARCH == arm64 ]] && echo -arm64):${TAG:-latest}\e[1;37m"
|
||||
echo "building locally and then pushing to ${REPO:-hub.docker.com}"
|
||||
if [[ ! $REPO ]]; then
|
||||
echo "NOTE: use target 'publish' to build and push these both"
|
||||
echo "to docker hub without architecture suffix or local copy"
|
||||
fi
|
||||
;;
|
||||
dev)
|
||||
;&
|
||||
default)
|
||||
echo -e "name => \e[1;31m$IMAGE_NAME:${TAG:-latest}\e[1;37m"
|
||||
echo "Will build this single image on this machine with architecture $ARCH"
|
||||
;;
|
||||
arm64)
|
||||
echo -e "name => \e[1;31m$IMAGE_NAME$([[ ! $ARCH == arm64 ]] && echo -arm64):${TAG:-latest}\e[1;37m"
|
||||
echo "Will build this single arm64 image on this machine"
|
||||
;;
|
||||
amd64)
|
||||
echo -e "name => \e[1;31m$IMAGE_NAME$([[ ! $ARCH == amd64 ]] && echo -amd64):${TAG:-latest}\e[1;37m"
|
||||
echo "Will build this single amd64 image on this machine"
|
||||
;;
|
||||
publish)
|
||||
echo -e "image name \e[1;31m$IMAGE_NAME:${TAG:-latest}\e[1;37m"
|
||||
echo "Will build and push both amd64 and arm64"
|
||||
echo "architecture images to hub.docker.com with this single name"
|
||||
echo "and no local copy will remain"
|
||||
|
||||
;;
|
||||
esac
|
||||
echo "------------------"
|
||||
echo -e "********************\e[0;37m"
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
declare libdir
|
||||
libdir=$(dirname "$(realpath "$BASH_SOURCE")")
|
||||
source $libdir/helpers.lib
|
||||
for f in $libdir/cmds/*; do
|
||||
for f in $libdir/cmds/*.sh; do
|
||||
# echo sourcing: $f >&2
|
||||
source "$f"
|
||||
done
|
||||
|
|
50
readme.md
50
readme.md
|
@ -1,52 +1,32 @@
|
|||
# UCI Docker Image Builder
|
||||
|
||||
Prerequistes:
|
||||
Easily build docker images for local use and publishing without messing around with a Dockerfile. Just some knowledge of BASH scripting is needed.
|
||||
|
||||
see https://hacking.kebler.net/Linux/Arch/docker/
|
||||
The "guts" of this repo is a single BASH shell script plus associated library to facilitate building docker linux images using any of four of these distros (arch,alpine,debian,ubuntu) and either architecture (amd64/arm64)
|
||||
|
||||
## About
|
||||
|
||||
## Prequisites
|
||||
You need docker daemon installed with some other installation particulars in order to build images
|
||||
|
||||
|
||||
The Dockerfile is assembled at build time is essentially two RUN commands. One to install packages (you specify) via a distro's package manager and then one to run a BASH init script that you write with specifics of initializing the image with whatever software the image is tasked to do. You specify those by setting a BUILD_SRC build source directory. This repo comes with a very basic build source which can handle any of the four distros mentioned. To build something more complicated you need to create your or src/ directory (see docs) or use one already developed (e.g. uci-docker-caddy repo)
|
||||
|
||||
<!-- assuming your current (dev) user is in the docker group
|
||||
for linking into volumes for the try command
|
||||
```
|
||||
sudo chown -R :docker /var/lib/docker
|
||||
sudo chmod -R g+r docker /var/lib/docker
|
||||
``` -->
|
||||
Baked into the initilization RUN is an entrypoint script that makes interacting with the image/container easy and also to launch your "custom" app within th container.
|
||||
|
||||
The build makes user of docker's "buildx bake" commands and a docker-bake.hcl file to make local images
|
||||
|
||||
|
||||
A build script plus associated library to facilitate building docker linux images using any of four distros (arch,alpine,debian,ubuntu) and either architecture (amd64/arm64)
|
||||
|
||||
The Dockerfile is minimal copying a directory and then calling a packages script and and init script in two RUN statements 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 master branch is configured to build base images from the docker hub distro base images
|
||||
|
||||
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 default build is simply a basic alpine image saved locally to alpine:lastest.
|
||||
|
||||
To run the ./build script from other repos install it using the install script
|
||||
|
||||
'./install
|
||||
|
||||
The repo also supports (with scripts) pushing to alternate private repositories packages (like a self hosted gitea or github)
|
||||
|
||||
One can make decendent images in one of two ways.
|
||||
One can make images in one of two ways.
|
||||
|
||||
1. Make your base images on the master branch (or a branch if you need to customize)
|
||||
2. User the installer script (./install) to link the build script into your system path. Then clone the template branch
|
||||
3.
|
||||
1. edit the /src directory on this master branch (or a better a branch)
|
||||
2. Use the installer script (./install) to link the build script into your system path. THen you can develop a BUILD_SRC src/ directory anywhere and call the build script from there
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
run
|
||||
|
||||
`./build -h`
|
||||
|
||||
for help
|
||||
|
||||
also see examples folder for example build environment file (more help details)
|
||||
It is recommended to do the later.
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/bash
|
||||
export SCRIPTS_DIR="$(dirname $(realpath "${BASH_SOURCE:-$0}"))"
|
||||
# echo arguments in entry $@
|
||||
# execute the start script in a login shell so that the uci shell will be sourced
|
||||
# see https://stackoverflow.com/a/1711985/4695378 passing $@
|
||||
/bin/bash -l -c '${SCRIPTS_DIR}/start.sh $@' $0 "$@"
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
# echo arguments in start script: "$@"
|
||||
source /opt/env/run.env
|
||||
source /opt/bin/host-id-map.sh
|
||||
case "$1" in
|
||||
cmd)
|
||||
shift 1
|
||||
"$@"
|
||||
;;
|
||||
script)
|
||||
shift 1
|
||||
module_load path
|
||||
script=$([[ $(isAbsPath $1) ]] && echo $1 || echo opt/bin/$1)
|
||||
shift 1
|
||||
/bin/bash $script "$@"
|
||||
;;
|
||||
*)
|
||||
/bin/bash -c "cd ${INITIAL_DIR:-$HOME}; exec bash -l"
|
||||
esac
|
|
@ -1 +0,0 @@
|
|||
base-entrypoint
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
if [[ $HOST_MAP ]]; then
|
||||
echo changing ownership of $VOLUME_DIRS to $HOST_MAP
|
||||
declare usesudo
|
||||
[[ ! $EUID -eq 0 ]] && usesudo=sudo
|
||||
$usesudo chown -R $HOST_MAP $VOLUME_DIRS
|
||||
fi
|
|
@ -1 +0,0 @@
|
|||
base-start
|
|
@ -0,0 +1,7 @@
|
|||
# anything in here will be sourced during build
|
||||
# allows easy custom environment variables
|
||||
|
||||
# by sourcing run.env in build will available in build
|
||||
[[ $ENV_DIR && -f $ENV_DIR/run.env ]] && source $ENV_DIR/run.env
|
||||
|
||||
# export VOLUME_DIRS="/opt"
|
|
@ -5,27 +5,20 @@ echo -e "\n##################################"
|
|||
# which useradd
|
||||
# which /bin/bash
|
||||
# echo SHELL $SHELL
|
||||
# groupadd -g 1000 host
|
||||
# useradd -r -g host -u 1000 host
|
||||
# git clone https://git.kebler.net/bash/shell-base.git /shell/base
|
||||
# export SHELL=/bin/bash
|
||||
# mkdir -p /home/sysadmin/shell
|
||||
# /bin/bash /shell/base/install/install.sh sysadmin
|
||||
# echo "******** uci shell install complete **********"
|
||||
# # make essential directories
|
||||
# mkdir -p $VOLUME_DIRS /opt/bin
|
||||
# chown -R :host /home/sysadmin/shell
|
||||
# chown -R host:host $VOLUME_DIRS
|
||||
# chmod -R g+rw /home/sysadmin/shell $VOLUME_DIRS
|
||||
# ls -la /home/sysadmin/shell $VOLUME_DIRS
|
||||
|
||||
groupadd -g 1000 host
|
||||
useradd -r -g host -u 1000 host
|
||||
groupadd -g 1001 sysadmin
|
||||
useradd -rm -s /bin/bash -G host,$([[ $(getent group sudo) ]] && echo sudo || echo wheel) -g sysadmin -u 1001 sysadmin
|
||||
echo sysadmin groups: $(groups sysadmin)
|
||||
chpasswd <<<"sysadmin:${SYSADMIN_PW:-sysadmin}"
|
||||
cp permitmod /etc/sudoers.d
|
||||
chmod 440 /etc/sudoers.d/permitmod
|
||||
|
||||
git clone https://git.kebler.net/bash/shell-base.git /shell/base
|
||||
export SHELL=/bin/bash
|
||||
mkdir -p /home/sysadmin/shell
|
||||
/bin/bash /shell/base/install/install.sh sysadmin
|
||||
echo "******** uci shell install complete **********"
|
||||
# make essential directories
|
||||
mkdir -p $VOLUME_DIRS /opt/bin
|
||||
chown -R :host /home/sysadmin/shell
|
||||
chown -R host:host $VOLUME_DIRS
|
||||
chmod -R g+rw /home/sysadmin/shell $VOLUME_DIRS
|
||||
ls -la /home/sysadmin/shell $VOLUME_DIRS
|
||||
echo installing and running image distro info
|
||||
/bin/bash install-os-info.sh
|
||||
/opt/bin/os-info
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# allow admins to change group and user ids
|
||||
sysadmin ALL = NOPASSWD : ALL
|
||||
# sysadmin ALL = NOPASSWD:/sbin/groupmod
|
||||
# sysadmin ALL = NOPASSWD:/sbin/usermod
|
||||
# sysadmin ALL = NOPASSWD:/sbin/adduser
|
||||
# sysadmin ALL = NOPASSWD:/sbin/addgroup
|
||||
# sysadmin ALL = NOPASSWD:/sbin/useradd
|
||||
# sysadmin ALL = NOPASSWD:/sbin/groudadd
|
|
@ -1,4 +0,0 @@
|
|||
# anything in here will be sourced during build
|
||||
# allows easy custom environment variables
|
||||
source /opt/env/run.env
|
||||
# export SOMEVAR="something"
|
|
@ -1,3 +1,3 @@
|
|||
# added /opt/run.env to the end of /etc/profile
|
||||
export VOLUME_DIRS="/shell /opt /data"
|
||||
export SHELL=/bin/bash
|
||||
export INITIAL_DIR=/opt
|
|
@ -0,0 +1,5 @@
|
|||
If you create/edit a image.info file in your source
|
||||
at the init/ subfolder then it will be including in the build
|
||||
as /opt/image.info.
|
||||
So this text comes from the default image.info file
|
||||
in the src/init folder of the default build source
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
echo "running base init.sh script in /build"
|
||||
# remove other distro files
|
||||
# find $PWD -maxdepth 1 -type d ! -path $PWD ! -name ${LINUX_DISTRO} ! -name common -exec rm -rf {} +
|
||||
|
|
|
@ -3,7 +3,6 @@ echo install packages for alpine distro
|
|||
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)
|
||||
# needed for useradd and groupadd
|
||||
apk add shadow --no-cache --repository=http://dl-2.alpinelinux.org/alpine/edge/community
|
||||
# apk add bindfs --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
|
||||
apk add --no-cache $(cat ./packages) $(cat ../common/packages)
|
||||
|
||||
|
||||
|
|
|
@ -5,3 +5,5 @@ rsync
|
|||
sudo
|
||||
nano
|
||||
coreutils
|
||||
bash
|
||||
bash-completion
|
|
@ -0,0 +1,2 @@
|
|||
export VOLUME_DIRS="/opt/bin"
|
||||
# export HOST_MAP="1001:1001"
|
|
@ -0,0 +1,11 @@
|
|||
# if SYSADMIN_PW is set a sysadmin user with uid of 1001 will be creted
|
||||
# SYSADMIN_PW=ucommandit
|
||||
# default is alpine
|
||||
# LINUX_DISTRO=alpine
|
||||
# prepend image name with this user, typically your docker hub user
|
||||
# RUSER=ucommandit
|
||||
RUSER=testing
|
||||
# default is default target, use dev for running a test container after build
|
||||
# TARGET=dev
|
||||
# by default will look in PWD directory then parent
|
||||
BUILD_SRC=../src
|
Loading…
Reference in New Issue