Skip to content

Instantly share code, notes, and snippets.

@allex
Last active December 8, 2020 10:00
Show Gist options
  • Save allex/0f2925a6140c67bf5379d1cddb748af4 to your computer and use it in GitHub Desktop.
Save allex/0f2925a6140c67bf5379d1cddb748af4 to your computer and use it in GitHub Desktop.
#!/bin/sh
# vim: set ft=sh fdm=manual ts=2 sw=2 sts=2 tw=85 et:
# ================================================
# Description: A docker build alternative impl, support squash and interactive build
# Usage:
# $ docker-build -t foo:1.0.0 -f ./Dockerfile --no-cache (all of native build args)
# -i interactive mode to maintain intermediate container
# Last Modified: Tue Dec 08, 2020 17:57
# Author: Allex Wang ([email protected])
# GistID: 0f2925a6140c67bf5379d1cddb748af4
# GistURL: https://gist.github.com/allex/0f2925a6140c67bf5379d1cddb748af4
# ================================================
set -euE -o pipefail
img_name=""
interactive=false
args=(" ")
while [ $# -gt 0 ]; do
v=${2-}
case "$1" in
-t | --tag)
img_name=$v
shift
;;
-i | --interactive)
interactive=true
;;
*)
args+=("$1")
;;
esac
shift
done
[ -n "$img_name" ] || {
echo >&2 "-t, --tag <img_name> Name and optionally a tag in the 'name:tag' format"
exit 1
}
eval set -- "${args[@]}"
#### Build intermediate image
echo "Step 0: Build intermediate image"
tmp_img="tmp.$$"
{
docker build -t $tmp_img "$@"
echo " --> ${tmp_img}"
trap '[ -n "$tmp_img" ] && docker rmi -f "$tmp_img" >/dev/null' 0 1 2 3 9 13 15
}
#### Squash image layers
echo "Step 1: Squash image layers"
intermediate_container=`docker run --net host --rm --entrypoint sh -id "$tmp_img" -l`
{
echo " --> Running in ${intermediate_container:0:12}"
while true; do docker inspect ${intermediate_container} -f '{{.Id}}' &>/dev/null && break; done
if ${interactive}; then
docker exec -it ${intermediate_container} sh -l || { echo >&2 "build abort."; exit 1; }
fi
}
#### Export as dist image
echo "Step 2: Export intermediate container to image '${img_name}'"
{
[ -n "${img_name}" ] || {
read -p "Enter new image name (in the 'name:tag' format) " img_name || exit 1
}
cfg=`docker inspect --format='{{if .Config.Labels}}LABEL {{range $k, $v := .Config.Labels}}{{$k}}="{{$v}}" {{end}}{{end}}
{{range .Config.Env}}ENV {{println .}}{{end}}
CMD [{{range $i, $v := .Config.Cmd}}{{if $i}}, {{end}}"{{$v}}"{{end}}]
ENTRYPOINT [{{range $i, $v := .Config.Entrypoint}}{{if $i}}, {{end}}{{printf "\"%s\"" .}}{{end}}]
{{if .Config.Volumes}}VOLUME [{{$index := 0}}{{range $k, $v := .Config.Volumes}}{{if $index}}, {{else}}{{$index = 1}}{{end}}{{printf "\"%s\"" $k}}{{end}}]{{end}}
' "${tmp_img}"`
cat <<DOC
inspect image config:
~~~
$cfg
~~~
DOC
image_id=`docker export ${intermediate_container} | \
docker import -m 'squash build' -c "$cfg" - ${img_name}`
echo " --> ${image_id#*:}"
}
echo "Removing intermediate container ${intermediate_container:0:12}"
docker kill ${intermediate_container} >/dev/null
docker images |grep "<none>" |awk '{print $3}' |xargs -I{} docker rmi -f {} > /dev/null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment