Last active
November 18, 2022 12:16
-
-
Save vaab/89d710f452b1d4fc7912 to your computer and use it in GitHub Desktop.
docker-update
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## Updates an existing image with given script coming from stdin. | |
## | |
exname=$(basename $0) | |
usage="$exname DOCKER_IMAGE | |
Update image with stdin instruction. | |
" | |
if [ -z "$1" ]; then | |
echo "Error: you should specify a parent image as first argument." >&2 | |
echo "usage: $usage" | |
exit 1 | |
fi | |
image="$1" | |
shift | |
DOCKER_VERSION=$(docker -v | sed -r 's/^[^0-9.]+([0-9.]+).*$/\1/g') | |
is_cached_code_same() { | |
local cmd | |
cmd="$@" | |
code="$(cat -)" | |
[ "$1" == "-c" ] || return 1 | |
[ "$2" == "$code" ] || return 1 | |
if echo "$code" | egrep "#\s*docker:\s*ALWAYS\s*" >/dev/null 2>&1; then | |
return 1 | |
fi | |
return 0 | |
} | |
DOCKER_INSPECT_CACHE_FORMAT='{{.Id}}{{"\x00"}} | |
{{.Parent}}{{"\x00"}} | |
{{if .Config}}{{range $p := .Config.Cmd}}{{$p}}{{"\x00"}} | |
{{end}}{{end}}{{"\x00"}}' | |
DOCKER_INSPECT_CACHE_FORMAT="$(echo "$DOCKER_INSPECT_CACHE_FORMAT" | tr -d "\n")" | |
export DOCKER_INSPECT_CACHE_FORMAT | |
## | |
# check_cache PARENT_IMAGE | |
# | |
# Checks if no already stored image has PARENT_IMAGE as parent and | |
# same code. If it founds such an image, it'll output its id in stdout | |
# and return 0 errlvl. Otherwise it'll return 1 errlvl. | |
check_cache() { | |
local image | |
image="$1" | |
shift | |
code="$(cat -)" | |
image_id=$(get_image_id "$image") | |
while read-0 id parent; do | |
cmd=() | |
while true; do | |
read-0 elt | |
if [ "$elt" ]; then | |
cmd=("${cmd[@]}" "$elt") | |
else | |
break | |
fi | |
done | |
if [ "$parent" != "$image_id" ]; then | |
continue | |
fi | |
if echo "$code" | is_cached_code_same "${cmd[@]}"; then | |
## not used "$id" as there is a spurious \n that is inserted by --format | |
echo $id | |
return 0 | |
fi | |
done < <(docker inspect --format "$DOCKER_INSPECT_CACHE_FORMAT" $(docker images -qa)) | |
return 1 | |
} | |
docker_update() { | |
local image | |
image="$1" | |
shift | |
code=$(cat -) | |
## Saving CMD and ENTRYPOINT | |
save_cmd=$(docker inspect --format='{{json .Config.Cmd}}' "$image") | |
save_entrypoint=$(docker inspect --format='{{json .Config.Entrypoint}}' "$image") | |
## Checking cache in case already built. | |
if cached=$(echo "$code" | check_cache "$image"); then | |
echo "cached" | |
docker tag "$cached" "$image" | |
else | |
## Running code in container | |
container_id=$(docker run -d \ | |
--entrypoint /bin/bash \ | |
"$@" "$image" -c \ | |
"$code" | |
) | |
if [ "$(docker wait "$container_id")" != "0" ]; then | |
echo "Update of image "$image" failed ! (container: $container_id)" | |
echo "=== code:" | |
echo "$code" | |
echo "=== logs:" | |
docker logs "$container_id" | |
exit 1 | |
fi | |
docker commit --author "$exname" --message "$exname" \ | |
"$container_id" "$image" >/dev/null && | |
docker rm $container_id >/dev/null | |
echo "updated" | |
fi | |
## Final commit to restore CMD and ENTRYPOINT | |
docker build -t "$image" - <<EOF >/dev/null 2>&1 | |
FROM $image | |
CMD $save_cmd | |
ENTRYPOINT $save_entrypoint | |
EOF | |
} | |
read-0() { | |
while [ "$1" ]; do | |
IFS=$'\0' read -r -d '' "$1" || return 1 | |
shift | |
done | |
} | |
get_image_id() { | |
docker inspect --format '{{.Id}}' "$1" | |
} | |
docker_update "$image" "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey, thanks for the scripts. It's very useful to me. :)
I forked it to make some little changes:
https://gist.github.com/caioariede/99dc77101289726754a1