Skip to content

Instantly share code, notes, and snippets.

@takei-yuya
Last active May 15, 2019 02:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takei-yuya/fccd77c66709b910f41bc2a2f182abac to your computer and use it in GitHub Desktop.
Save takei-yuya/fccd77c66709b910f41bc2a2f182abac to your computer and use it in GitHub Desktop.
#!/bin/bash
set -e
scriptdir="$(cd "$(dirname "$0")"; pwd)"
script="${scriptdir%/}/$(basename "$0")"
readonly IMAGE_DIR="${HOME}/images/"
# escape docker tag for filename
escape() {
for (( i = 0; i < "${#1}"; ++i )); do
case "${1:i:1}" in
":"|"/")
printf '%%%X' "'${1:i:1}"
;;
*)
printf '%c' "${1:i:1}"
;;
esac
done
}
pull_image() {
mkdir -p "${IMAGE_DIR}"
local repo="${1}"
local tag="${2}"
if [ -d "${IMAGE_DIR}/layers/$(escape "${repo}:${tag}")" ]; then
# already exist
return
fi
local tmpdir="$(mktemp -d)"
trap "rm -rf '${tmpdir}'" RETURN
local token="$(curl -sSf -L "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull" | jq -rc .token)"
curl -sSf -L --header "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/${repo}/manifests/${tag}" -o "${tmpdir}/manifest"
local blobs=($(jq -rc '.fsLayers | .[].blobSum' "${tmpdir}/manifest"))
local ids=($(jq -rc '.history | .[].v1Compatibility | fromjson | .id' "${tmpdir}/manifest"))
local parents=($(jq -rc '.history | .[].v1Compatibility | fromjson | .parent' "${tmpdir}/manifest"))
local sha256s=("${blobs[@]#sha256:}")
for ((i = 0; i < ${#sha256s[@]}; ++i)); do
if [ ! -f "${IMAGE_DIR}/blobs/${sha256s[i]}.tar-split.gz" ]; then
mkdir -p "${IMAGE_DIR}/blobs/"
curl -Sf -L --header "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/${repo}/blobs/sha256:${sha256s[i]}" -o "${IMAGE_DIR}/blobs/${sha256s[i]}.tar-split.gz"
fi
if [ ! -d "${IMAGE_DIR}/blobs/${sha256s[i]}" ]; then
mkdir -p "${IMAGE_DIR}/blobs/${sha256s[i]}"
tar -C "${IMAGE_DIR}/blobs/${sha256s[i]}" -zxf "${IMAGE_DIR}/blobs/${sha256s[i]}.tar-split.gz"
fi
mkdir -p "${IMAGE_DIR}/layers/${ids[i]}"
if [ "${parents[i]}" != "null" ]; then
ln -T -sf "../${parents[i]}" "${IMAGE_DIR}/layers/${ids[i]}/parent"
fi
ln -T -sf "../../blobs/${sha256s[i]}.tar-split.gz" "${IMAGE_DIR}/layers/${ids[i]}/blob.tar-split.gz"
ln -T -sf "../../blobs/${sha256s[i]}" "${IMAGE_DIR}/layers/${ids[i]}/blob"
done
ln -T -sf "${ids[0]}" "${IMAGE_DIR}/layers/$(escape "${repo}:${tag}")"
}
if [ $# -lt 2 ]; then
echo "Usage: $0 REPO TAG"
exit 1
fi
pull_image "$1" "$2"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment