#!/bin/bash ################################################################################ set -eEuo pipefail err=0 trap 'err=$?' ERR trap 'cleanup' EXIT epoch=$(date +%s.%3N) today=$(date +%Y-%m-%d-T%H%M) badarg() { echo -n "$(basename $0): " echo "$1" echo "Try '$(basename $0) -h' for more information." exit 2 } cleanup() { if [[ $err -eq 0 || $opt_debug -eq 0 ]]; then podman rm -i -f tmp-$epoch 2>&1 > /dev/null fi } help="Usage: $(basename $0) [-sdh] [-t tag] [directory] [name] Builds an image from files in a directory, and assigns it a name. Files used are 'Containerfile' and optionally 'Systemdfile'. If first argument is omitted, script assumes files can be found in the current working directory. If second argument is omitted, the directory where the files were found is used as the image name. Options: -s Squash all newly built layers in the image into a single layer -d Debug mode: don't delete the temporary container created by the script when encountering an error -t [tag] Tag the image with the given string. Can be used multiple times to assign multiple tags -h Display this help and exit" # Handle options opt_squash=0 opt_debug=0 opt_tags=() while getopts ':sdt:h' arg; do case $arg in s) opt_squash=1;; d) opt_debug=1;; t) opt_tags+=("${OPTARG}");; h) echo "$help"; exit 0;; :) badarg "Argument missing for option '-$OPTARG'";; ?) badarg "Invalid option '-$OPTARG'";; esac done # Handle non-option arguments if [[ $# -gt 2 ]]; then badarg "Too many arguments" fi if [[ $# -ge 1 ]]; then directory="$1" else directory=$(pwd) fi if [[ $# -ge 2 ]]; then name="$2" else name=$(basename "$directory") fi # Main if [[ ! -d "$directory" ]]; then echo "Error: directory '$directory' not found" exit 1 else cd "$directory" fi buildopts="" if [[ $opt_squash -eq 1 ]]; then buildopts="$buildopts --squash" fi # tell buildah to build images in docker format instead of the default OCI format # because only docker-format images can use the SHELL directive in Containerfiles export BUILDAH_FORMAT=docker # build image echo "Building image ..." podman build -f Containerfile -t tmp-$epoch $buildopts # Systemdfile is for commands that need systemd to execute if [[ -f Systemdfile ]]; then echo "Running build steps that require systemd ..." echo "Creating temporary container ..." podman create --name tmp-$epoch tmp-$epoch podman start tmp-$epoch echo "Copying script to container ..." podman cp Systemdfile tmp-$epoch:/root/ echo "Running script ..." podman exec tmp-$epoch bash -c "chmod +x /root/Systemdfile && /root/Systemdfile" echo "Committing container to image ..." podman commit tmp-$epoch "$name:$today" else echo "Systemdfile not found, skipping temporary container step ..." # tag image we already built with appropriate tag, and untag with tmp podman tag tmp-$epoch "$name:$today" podman rmi tmp-$epoch fi # assign any extra tags for tag in "${opt_tags[@]}"; do podman tag "$name:$today" "$name:$tag" done echo "Done!"