Skip to content

Instantly share code, notes, and snippets.

@vaab
Last active November 18, 2022 12:16
Show Gist options
  • Select an option

  • Save vaab/89d710f452b1d4fc7912 to your computer and use it in GitHub Desktop.

Select an option

Save vaab/89d710f452b1d4fc7912 to your computer and use it in GitHub Desktop.

Revisions

  1. vaab revised this gist Jan 27, 2015. 1 changed file with 14 additions and 4 deletions.
    18 changes: 14 additions & 4 deletions docker-update
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,6 @@

    ## Updates an existing image with given script coming from stdin.
    ##
    ## $exname build NAME CHARM
    ##

    exname=$(basename $0)

    @@ -12,7 +10,6 @@ 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"
    @@ -86,12 +83,20 @@ docker_update() {
    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 \
    @@ -106,12 +111,14 @@ docker_update() {
    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
    @@ -129,8 +136,11 @@ read-0() {
    shift
    done
    }


    get_image_id() {
    docker inspect --format '{{.Id}}' "$1"
    }


    docker_update "$image" "$@"
  2. vaab created this gist Jan 27, 2015.
    136 changes: 136 additions & 0 deletions docker-update
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,136 @@
    #!/bin/bash

    ## Updates an existing image with given script coming from stdin.
    ##
    ## $exname build NAME CHARM
    ##

    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 -)

    save_cmd=$(docker inspect --format='{{json .Config.Cmd}}' "$image")
    save_entrypoint=$(docker inspect --format='{{json .Config.Entrypoint}}' "$image")
    if cached=$(echo "$code" | check_cache "$image"); then
    echo "cached"
    docker tag "$cached" "$image"
    else
    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
    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" "$@"