Skip to content

Instantly share code, notes, and snippets.

@mnl
Last active February 17, 2024 15:16
Show Gist options
  • Save mnl/6f9d5fe7a2acda58ef0afcf806107215 to your computer and use it in GitHub Desktop.
Save mnl/6f9d5fe7a2acda58ef0afcf806107215 to your computer and use it in GitHub Desktop.
docker build hook

Build images on tag push

Prepare build machine / remote repo

  • Create remote repo (suffix .git is convention for bare repos) git init --bare myrepo.git

  • Add docker build hook cp post-receive.bash myrepo/hooks/post-receive

  • Make sure docker build runs without any problems

Prepare workstation

  • Set up ssh-keys so git can login via ssh (optional)
    ssh-copy-id -i mygitkey user@mygitserver

  • Set up alias in ~/.ssh/config for repo server (also optional)

Host myreposerver
         User myuser
         Port 2222
         HostName reposerver.example.com
         IdentityFile mygitkey
  • In the git repo, make sure you have a valid Dockerfile

  • Add remote (origin or whatever name)
    git remote add origin ssh://myreposerver/path/to/myrepo.git

  • Add a tag to a commot you wat to build
    git tag v0.1

  • Push tags
    git push origin main --tags

  • Build starts

#!/bin/bash
# Git hook that builds a container when a new tag is received
# post receive hooks are run at the end so client hangs until build is done
# shellcheck disable=SC2034
cleanup() {
rm -rf "${builddir}"
}
build_tag() {
builddir=$(mktemp -d -t XXXX-build)
trap cleanup EXIT
repodir=$PWD
cd "${builddir}" || exit
umask 0002 # make sure rootless docker can read build context
git clone -b "${tagname}" "${repodir}" -c advice.detachedHead=false .
if [[ ! -r Dockerfile ]]; then
echo "No Dockerfile found."
exit 0
fi
# Build and tag container. Dockerfile should have build-args set
docker build \
--build-arg="TAGNAME=${tagname}" \
--build-arg="AUTHOR=$(git --git-dir "${builddir}"/.git log --format='%an %ae' HEAD^\!)" \
--build-arg="BUILD_TIME=$(date --iso-8601=minutes)" \
--build-arg="COMMIT=$(git --git-dir "${builddir}"/.git rev-parse HEAD)" \
--tag "$(basename "${repodir}")":"${tagname}" \
--file ./Dockerfile src
}
process_ref() {
case ${refname} in
refs/tags/*)
tagname=${refname##refs/tags/}
;;
refs/heads/*)
;;
esac
}
# Hook input:
# <old-value> SP <new-value> SP <ref-name> LF
while IFS=' ' read -r oldref newref refname; do process_ref "${refname}"; done
# All refs processed
if [[ -z ${tagname} ]]; then
# no tags to build
echo no tags to build
exit 0
fi
# Build last tag (if multiple tags were pushed)
echo "Starting build of tag: ${tagname}"
build_tag "${tagname}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment