ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ืžื™ืจ ื”ืึธื‘ืŸ 2 ื‘ืึทื’ืก ืคื•ืŸ ื’ืจืึธื–, 75 ืžืขืกืงืึทืœื™ื ืข ื˜ืึทื‘ืœืึทืฅ ื™ื•ื ื™ืงืก ืกื•ื•ื™ื•ื•ืข, ืึท ื“ืึธืงืงืขืจ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืื•ืŸ ื“ื™ ืึทืจื‘ืขื˜ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื“ื™ ื“ืึทืงืขืจ ืฆื™ืขืŸ ืื•ืŸ ื“ืึทืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜.

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

UPD:
ืคืจืื’ืข: ื•ื•ืึธืก ืื™ื– ื“ืึธืก ืึทืœืข ืคึฟืึทืจ?
ืขื ื˜ืคืขืจ: ืžืึทืกืข ื˜ืขืกื˜ื™ื ื’ ืคื•ืŸ ื“ื™ ืคึผืจืึธื“ื•ืงื˜ (ื ื™ืฉื˜ ื ื™ืฆืŸ ื‘ืึทืฉ, ื“ื™ ืกืงืจื™ืคึผืก ื–ืขื ืขืŸ ืฆื•ื’ืขืฉื˜ืขืœื˜ ืคึฟืึทืจ ื‘ื™ืœื“ื•ื ื’ืงืจื™ื™ื– ืฆื•ื•ืขืงืŸ). ืขืก ืื™ื– ื‘ืึทืฉืœืึธืกืŸ ื ื™ืฉื˜ ืฆื• ื ื•ืฆืŸ ื“ื™ ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ืฆื• ืจืขื“ื•ืฆื™ืจืŸ ื ืึธืš ืœื™ื™ึทืขืจืก (ืื™ืŸ ื’ืœื™ื™ึทืš ืœื™ืžืึทืฅ) ืื•ืŸ, ืึทืงืึธืจื“ื™ื ื’ืœื™, ืขืžื™ืึทืœื™ื™ื˜ ืึท ื”ืขื›ืขืจ ืžืึทืกืข. ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ืึทืœืข ืกื™ืกื˜ืขื ื“ื™ืœื™ื™ื– ืคื•ืŸ ื“ื™ ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื–ืขื ืขืŸ ืึทื•ื•ืขืงื’ืขื ื•ืžืขืŸ. ืžื™ืจ ื‘ืืงื•ืžืขืŸ ืึท ืœืขืคื™ืขืจืขืš ืจื™ื™ืŸ ืžืึทืกืข ื’ืœื™ื™ึทืš ืื•ื™ืฃ ื“ืขื ืคึผืจืึธื“ื•ืงื˜.
ื“ืขืจ ืึทืจื˜ื™ืงืœ ื’ืขื•ื•ื™ื™ื ื˜ GNU ื•ื•ืขืจืกื™ืขืก ืคื•ืŸ ืžื›ืฉื™ืจื™ื.

ืขืจืฉื˜ืขืจ, ืœืึธื–ืŸ ืก ืจืขื›ืขื ืขืŸ ืื•ื™ืก ื•ื•ืึธืก ื“ื™ ืงืึทืžืึทื ื“ื– ื˜ืึธืŸ.

ืึทื–ื•ื™ ื•ื•ืึธืก ืื™ื– ื“ืึธืงืขืจ ืฆื™ืขืŸ ื’ืขื ื™ืฆื˜ ืคึฟืึทืจ? ืœื•ื™ื˜ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ:

"ืฆื™ืขืŸ ืึท ื‘ื™ืœื“ ืึธื“ืขืจ ืึท ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืคื•ืŸ ืึท ืจืขื’ื™ืกื˜ืจื™".

ื“ืึธ ืžื™ืจ ืื•ื™ืš ื’ืขืคึฟื™ื ืขืŸ ืึท ืœื™ื ืง ืฆื• ืคึฟืึทืจืฉื˜ื™ื™ืŸ ื‘ื™ืœื“ืขืจ, ืงืึทื ื˜ื™ื™ื ืขืจื– ืื•ืŸ ืกื˜ืึธืจื™ื“ื–ืฉ ื“ืจื™ื•ื•ืขืจืก.

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ืคื•ืŸ ื“ืึธ ืžื™ืจ ืงืขื ืขืŸ ืคึฟืึทืจืฉื˜ื™ื™ืŸ ืึทื– ืึท ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืื™ื– ืึท ืกื›ื•ื ืคื•ืŸ ื–ื™ื›ืขืจ ืœื™ื™ึทืขืจืก ื•ื•ืึธืก ืึทื ื˜ื”ืึทืœื˜ืŸ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ื•ื•ืขื’ืŸ ื“ื™ ืœืขืฆื˜ืข ืขื ื“ืขืจื•ื ื’ืขืŸ ืื™ืŸ ื“ื™ ื‘ื™ืœื“, ื•ื•ืึธืก ืื™ื– ื“ืึธืš ื•ื•ืึธืก ืžื™ืจ ื“ืึทืจืคึฟืŸ. ื•ื•ื™ื™ึทื˜ืขืจ ืžื™ืจ ืงื•ืงืŸ ืื™ืŸ ืจืขื’ื™ืกื˜ืจื™ ืึทืคึผื™.

ืขืก ื–ืื’ื˜ ื“ื™ ืคืืœื’ืขื ื“ืข:

"ื "ื‘ื™ืœื“" ืื™ื– ืึท ืงืึธืžื‘ื™ื ืึทืฆื™ืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ืึท JSON ืžืึทื ื™ืคืขืกื˜ ืื•ืŸ ื™ื—ื™ื“ ืฉื™ื›ื˜ืข ื˜ืขืงืขืก. ื“ืขืจ ืคึผืจืึธืฆืขืก ืคื•ืŸ ืคึผื•ืœื™ื ื’ ืึท > ื‘ื™ืœื“ ืกืขื ื˜ืขืจืก ืึทืจื•ื ืจื™ื˜ืจื™ื•ื•ื™ื ื’ ื“ื™ ืฆื•ื•ื™ื™ ืงืึทืžืคึผืึธื•ื ืึทื ืฅ."

ืึทื–ื•ื™ ื“ืขืจ ืขืจืฉื˜ืขืจ ืฉืจื™ื˜ ืœื•ื™ื˜ ื“ื™ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ ืื™ื– "ืคึผื•ืœื™ื ื’ ืึท ื‘ื™ืœื“ ืžืึทื ื™ืคืขืกื˜".

ืคื•ืŸ ืงื•ืจืก, ืžื™ืจ ื•ื•ืขืœืŸ ื ื™ืฉื˜ ื“ืจื™ื™ืขืŸ ืขืก, ืึธื‘ืขืจ ืžื™ืจ ื“ืึทืจืคึฟืŸ ื“ื™ ื“ืึทื˜ืŸ ืคื•ืŸ ืขืก. ื“ื™ ืคืืœื’ืขื ื“ืข ืื™ื– ืึท ื‘ื™ื™ึทืฉืคึผื™ืœ ื‘ืงืฉื”: GET /v2/{name}/manifests/{reference}

"ื“ื™ ื ืึธืžืขืŸ ืื•ืŸ ืจืขืคึฟืขืจืขื ืฅ ืคึผืึทืจืึทืžืขื˜ืขืจ ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ ื“ื™ ื‘ื™ืœื“ ืื•ืŸ ื–ืขื ืขืŸ ืคืืจืœืื ื’ื˜. ื“ืขืจ ืจืขืคึฟืขืจืขื ืฅ ืงืขืŸ ืึทืจื™ื™ึทื ื ืขืžืขืŸ ืึท ืงื•ื•ื™ื˜ืœ ืึธื“ืขืจ ื“ื™ื™ื“ื–ืฉืขืกื˜."

ืื•ื ื“ื–ืขืจ ื“ืึธืงืงืขืจ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืื™ื– ื“ื™ืคึผืœื•ื™ื“ ืœืึธื•ืงืึทืœื™, ืœืึธื–ืŸ ืื•ื ื“ื– ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ื•ื™ืกืคื™ืจืŸ ื“ื™ ื‘ืงืฉื”:

curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/manifests/1.1.1" -H "header_if_needed"

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ืื™ืŸ ืขื ื˜ืคืขืจ, ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ื“ื–ืฉืกืึธืŸ ืคื•ืŸ ื•ื•ืึธืก ืžื™ืจ ื–ืขื ืขืŸ ื“ืขืจื•ื•ื™ื™ึทืœ ื‘ืœื•ื™ื– ืื™ื ื˜ืขืจืขืกื™ืจื˜ ืื™ืŸ ื“ื™ ืœื™ื™ืงืœื™ื™ื ื–, ืึธื“ืขืจ ื’ืึทื ืฅ ื–ื™ื™ืขืจ ื”ืึทืฉืขืก. ื ืึธืš ื‘ืืงื•ืžืขืŸ ื–ื™ื™, ืžื™ืจ ืงืขื ืขืŸ ื’ื™ื™ืŸ ื“ื•ืจืš ื™ืขื“ืขืจ ืื™ื™ื ืขืจ ืื•ืŸ ื•ื™ืกืคื™ืจืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ื‘ืขื˜ืŸ: "GET /v2/{name}/blobs/{ื“ื™ื’ืขืกื˜}"

"ืฆื•ื˜ืจื™ื˜ ืฆื• ืึท ืฉื™ื›ื˜ืข ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ื™ื™ื˜ื™ื“ ื“ื•ืจืš ื“ื™ ื ืึธืžืขืŸ ืคื•ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืึธื‘ืขืจ ืื™ื– ื™ื™ื“ืขื ืึทืคื™ื™ื“ ื™ื•ื ื™ืงืœื™ ืื™ืŸ ื“ื™ ืจืขื’ื™ืกื˜ืจื™ ื“ื•ืจืš ื“ื™ื™ื“ื–ืฉืขืกื˜."

ื“ื™ื™ื“ื–ืฉืขืกื˜ ืื™ืŸ ื“ืขื ืคืึทืœ ืื™ื– ื“ื™ ื”ืึทืฉ ื•ื•ืึธืก ืžื™ืจ ื‘ืืงื•ืžืขืŸ.

ื˜ืจื™ื™ื ื’

curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/blobs/sha256:f972d139738dfcd1519fd2461815651336ee25a8b54c358834c50af094bb262f" -H "header_if_needed" --output firstLayer

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ืœืึธืžื™ืจ ื–ืขืŸ ื•ื•ืึธืก ืคึฟืึทืจ ืึท ื˜ืขืงืข ืžื™ืจ ืœืขืกืึธืฃ ื‘ืืงื•ืžืขืŸ ื•ื•ื™ ื“ืขืจ ืขืจืฉื˜ืขืจ ืœื™ื™ืคืœื™ื™ืŸ.

file firstLayer

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ื™ืขื ืข. ืจื™ื™ืœื– ื–ืขื ืขืŸ ื˜ืึทืจ ืึทืจืงื™ื™ื•ื•ื–, ืึทื ืคึผืึทืงื™ื ื’ ื–ื™ื™ ืื™ืŸ ื“ื™ ืฆื•ื ืขืžืขืŸ ืกื“ืจ ืžื™ืจ ื•ื•ืขืœืŸ ื‘ืึทืงื•ืžืขืŸ ื“ื™ ืื™ื ื”ืึทืœื˜ ืคื•ืŸ ื“ื™ ื‘ื™ืœื“.

ืœืึธืžื™ืจ ืฉืจื™ื™ึทื‘ืŸ ืึท ืงืœื™ื™ืŸ ื‘ืึทืฉ ืฉืจื™ืคื˜ ืึทื–ื•ื™ ืึทื– ืึทืœืข ื“ืขื ืงืขื ืขืŸ ื–ื™ื™ืŸ ืึธื˜ืึทืžื™ื™ื˜ื™ื“

#!/bin/bash -eu

downloadDir=$1
# url as http://localhost:8081/link/to/docker/registry
url=$2
imageName=$3
tag=$4

# array of layers
layers=($(curl -s -X GET "$url/v2/$imageName/manifests/$tag" | grep -oP '(?<=blobSum" : ").+(?=")'))

# download each layer from array
for layer in "${layers[@]}"; do
    echo "Downloading ${layer}"
    curl -v -X GET "$url/v2/$imageName/blobs/$layer" --output "$downloadDir/$layer.tar"
done

# find all layers, untar them and remove source .tar files
cd "$downloadDir" && find . -name "sha256:*" -exec tar xvf {} ;
rm sha256:*.tar
exit 0

ืื™ืฆื˜ ืžื™ืจ ืงืขื ืขืŸ ืœื•ื™ืคืŸ ืขืก ืžื™ื˜ ื“ื™ ื’ืขื‘ืขื˜ืŸ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืื•ืŸ ื‘ืึทืงื•ืžืขืŸ ื“ื™ ืื™ื ื”ืึทืœื˜ ืคื•ืŸ ื“ื™ ืคืืจืœืื ื’ื˜ ื‘ื™ืœื“

./script.sh dirName โ€œhttp://localhost:8081/link/to/docker/registryโ€ myAwesomeImage 1.0

ื˜ื™ื™ืœ 2 - ื“ืึธืงืงืขืจ ืฉื˜ื•ืคึผืŸ

ื“ืึธืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ืึท ื‘ื™ืกืœ ืžืขืจ ืงืึธืžืคึผืœื™ืฆื™ืจื˜.

ื–ืืœ ืก ืึธื ื”ื™ื™ื‘ืŸ ื•ื•ื™ื“ืขืจ ืžื™ื˜ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ. ืึทื–ื•ื™ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืึธืคึผืœืึธื“ื™ืจืŸ ื™ืขื“ืขืจ ืคื™ืจืขืจ, ืงืœื™ื™ึทื‘ืŸ ื“ื™ ืงืึธืจืึทืกืคึผืึทื ื“ื™ื ื’ ื‘ืึทืฉื™ื™ึทืžืคึผืขืจืœืขืš ืื•ืŸ ืืจืืคืงืืคื™ืข ืขืก ืื•ื™ืš. ืขืก ืžื™ื™ื ื˜ ืคึผืฉื•ื˜.

ื ืึธืš ืœืขืจื ืขืŸ ื“ื™ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ, ืžื™ืจ ืงืขื ืขืŸ ื˜ื™ื™ืœืŸ ื“ื™ ืืจืืคืงืืคื™ืข ืคึผืจืึธืฆืขืก ืื™ืŸ ืขื˜ืœืขื›ืข ืกื˜ืขืคึผืก:

  • ืคึผืจืึธืฆืขืก ื™ื ื™ื˜ื™ืึทืœื™ื–ืึทื˜ื™ืึธืŸ - "POST /v2/{repoName}/blobs/uploads/"
  • ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท ืœื™ื™ืคืœื™ื™ืŸ (ืžื™ืจ ื•ื•ืขืœืŸ ื ื•ืฆืŸ ืึท ืžืึทื ืึทืœื™ื˜ื™ืง ื•ืคึผืœืึธืึทื“, ื“"ื” ืžื™ืจ ืฉื™ืงืŸ ื™ืขื“ืขืจ ืœื™ื™ืคืœื™ื™ืŸ ืื™ืŸ ื–ื™ื™ืŸ ื’ืึทื ืฅ) - "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={ื“ื™ื’ืขืกื˜}
    ืื™ื ื”ืึทืœื˜-ืœืขื ื’: {ื’ืจื™ื™ืก ืคื•ืŸ ืฉื™ื›ื˜ืข}
    ืื™ื ื”ืึทืœื˜-ื˜ื™ืคึผ: ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ / ืึธืงื˜ืขื˜-ืกื˜ืจื™ื
    ืฉื™ื›ื˜ืข ื‘ื™ื™ื ืขืจื™ ื“ืึทื˜ืึท".
  • ืœืึธื•ื“ื™ื ื’ ื“ื™ ืžืึทื ืึทืคืขืกื˜ื™ื™ืฉืึทืŸ - "PUT /v2/{repoName}/manifests/{reference}".

ืื‘ืขืจ ื“ื™ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ ืคืขืœืŸ ืื™ื™ืŸ ืฉืจื™ื˜, ืึธืŸ ื•ื•ืึธืก ื’ืึธืจื ื™ืฉื˜ ื•ื•ืขื˜ ืึทืจื‘ืขื˜ืŸ. ืคึฟืึทืจ ืžืึทื ืึทืœื™ื˜ื™ืง ืœืึธื•ื“ื™ื ื’, ื•ื•ื™ ื’ืขื–ื•ื ื˜ ื•ื•ื™ ืคึฟืึทืจ ืคึผืึทืจื˜ื™ื™ื™ืฉ (ื˜ืฉื•ื ืงืขื“), ืื™ื™ื“ืขืจ ืœืึธื•ื“ื™ื ื’ ื“ื™ ืจืขืœืก, ืื™ืจ ืžื•ื–ืŸ ื“ื•ืจื›ืคื™ืจืŸ ืึท ืคึผืึทื˜ืฉ ื‘ืขื˜ืŸ:

"ืคึผืึทื˜ืฉ /v2/{repoName}/blobs/uploads/{uuid}
ืื™ื ื”ืึทืœื˜-ืœืขื ื’: {ื’ืจื™ื™ืก ืคื•ืŸ ืฉื˜ื™ืง}
ืื™ื ื”ืึทืœื˜-ื˜ื™ืคึผ: ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ / ืึธืงื˜ืขื˜-ืกื˜ืจื™ื
{ืฉื™ื›ื˜ืข ื˜ืฉืึทื ื’ ื‘ื™ื™ื ืขืจื™ ื“ืึทื˜ืึท}".

ืึทื ื“ืขืจืฉ, ืื™ืจ ื•ื•ืขื˜ ื ื™ืฉื˜ ืงืขื ืขืŸ ืฆื• ืจื™ืจืŸ ื•ื•ื™ื™ึทื˜ืขืจ ืคื•ืŸ ื“ืขืจ ืขืจืฉื˜ืขืจ ืคื•ื ื˜, ื•ื•ื™ื™ึทืœ ... ืึทื ืฉื˜ืึธื˜ ื“ื™ ื“ืขืจื•ื•ืึทืจื˜ ืขื ื˜ืคืขืจ ืงืึธื“ 202, ืื™ืจ ื•ื•ืขื˜ ื‘ืึทืงื•ืžืขืŸ 4xx.

ืื™ืฆื˜ ื“ืขืจ ืึทืœื’ืขืจื™ื“ืึทื ืงื•ืงื˜ ื•ื•ื™:

  • ื™ื ื™ื˜ื™ืึทืœื™ื–ืึทื˜ื™ืึธืŸ
  • ืคึผืึทื˜ืฉ ืจืขืœืก
  • ืœืึธื•ื“ื™ื ื’ ื“ื™ ื”ืึทื ื˜ืจืขื™ืœ
  • ืœืึธื•ื“ื™ื ื’ ื“ื™ ืžืึทื ืึทืคืขืกื˜ื™ื™ืฉืึทืŸ
    ื“ื™ ืคื•ื ืงื˜ืŸ 2 ืื•ืŸ 3, ืจื™ืกืคึผืขืงื˜ื™ื•ื•ืœื™, ื•ื•ืขื˜ ื–ื™ื™ืŸ ืจื™ืคึผื™ื˜ื™ื“ ืึทื–ื•ื™ ืคื™ืœืข ืžืึธืœ ื•ื•ื™ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืฉื•ืจื•ืช ื“ืึทืจืฃ ื–ื™ื™ืŸ ืœืึธื•ื“ื™ื“.

ืขืจืฉื˜ืขืจ, ืžื™ืจ ื“ืึทืจืคึฟืŸ ืงื™ื™ืŸ ื‘ื™ืœื“. ืื™ืš ื•ื•ืขืœ ื ื•ืฆืŸ archlinux: ืœืขืฆื˜

docker pull archlinux

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ืื™ืฆื˜ ืœืึธื–ืŸ ืื•ื ื“ื– ืจืึทื˜ืขื•ื•ืขืŸ ืขืก ืœืึธื•ืงืึทืœื™ ืคึฟืึทืจ ื•ื•ื™ื™ึทื˜ืขืจ ืึทื ืึทืœื™ืกื™ืก

docker save c24fe13d37b9 -o savedArch

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ื•ื ืคึผืึทืง ื“ื™ ืจื™ื–ืึทืœื˜ื™ื ื’ ืึทืจืงื™ื™ื•ื• ืื™ืŸ ื“ื™ ืงืจืึทื ื˜ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ

tar xvf savedArch

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ื•ื•ื™ ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ, ื™ืขื“ืขืจ ืœื™ื™ืคืœื™ื™ืŸ ืื™ื– ืื™ืŸ ืึท ื‘ืึทื–ื•ื ื“ืขืจ ื˜ืขืงืข. ืื™ืฆื˜ ืœืึธืžื™ืจ ืงื•ืงืŸ ืื™ืŸ ื“ื™ ืกื˜ืจื•ืงื˜ื•ืจ ืคื•ืŸ ื“ื™ ืžืึทื ืึทืคืขืกื˜ื™ื™ืฉืึทืŸ ื•ื•ืึธืก ืžื™ืจ ื‘ืืงื•ืžืขืŸ

cat manifest.json | json_pp

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ื ื™ืฉื˜ ืืกืืš. ื–ืืœ ืก ื–ืขืŸ ื•ื•ืึธืก ืžืึทื ื™ืคืขืกื˜ ืื™ื– ื“ืืจืฃ ืฆื• ืžืึทืกืข, ืœื•ื™ื˜ ืฆื• ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ.

ื™ืžืคึผืœืขืžืขื ื˜ื™ื ื’ ื“ืึธืงืงืขืจ ืคึผื•ืœ ืื•ืŸ ื“ืึธืงืขืจ ืฉื˜ื•ืคึผืŸ ืงืึทืžืึทื ื“ื– ืึธืŸ ืึท ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ื ื™ืฆืŸ HTTP ืจื™ืงื•ื•ืขืก

ื“ืึธืš, ื“ื™ ื™ื’ื–ื™ืกื˜ื™ื ื’ ืžืึทื ื™ืคืขืกื˜ืึธ ืื™ื– ื ื™ืฉื˜ ืคึผืึทืกื™ืง ืคึฟืึทืจ ืื•ื ื“ื–, ืึทื–ื•ื™ ืžื™ืจ ื•ื•ืขืœืŸ ืžืึทื›ืŸ ืื•ื ื“ื–ืขืจ ืื™ื™ื’ืขื ืข ืžื™ื˜ ื‘ืœืึทืงื“ื–ืฉืึทืง ืื•ืŸ ืงืึธื•ืจื˜ื™ื–ืึทื ืก, ืœื™ื™ืคืœื™ื ื– ืื•ืŸ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทื ื–.

ืžื™ืจ ื•ื•ืขืœืŸ ืฉื˜ืขื ื“ื™ืง ื”ืึธื‘ืŸ ื‘ื™ื™ึท ืžื™ื ื“ืกื˜ืขืจ ืื™ื™ืŸ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื˜ืขืงืข ืื•ืŸ ืึท ืžืขื ื’ืข ืคื•ืŸ โ€‹โ€‹ืœื™ื™ืคืœื™ื ื–. ืกื›ืขืžืข ื•ื•ืขืจืกื™ืข 2 (ืงืจืึทื ื˜ ืื™ืŸ ื“ืขืจ ืฆื™ื™ื˜ ืคื•ืŸ ืฉืจื™ื™ื‘ืŸ), MediaType ื•ื•ืขื˜ ื–ื™ื™ืŸ ืึทื ื˜ืฉื™ื™ื ื“ื–ืฉื“:

echo โ€˜{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": config_size,
      "digest": "config_hash"
   },
   "layers": [
      โ€™ > manifest.json

ื ืึธืš ืงืจื™ื™ื™ื˜ื™ื ื’ ื“ื™ ื™ืงืขืจื“ื™ืง ื‘ืึทืฉื™ื™ึทืžืคึผืขืจืœืขืš, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืคึผืœืึธืžื‘ื™ืจืŸ ืขืก ืžื™ื˜ ื’ื™ืœื˜ื™ืง ื“ืึทื˜ืŸ. ืฆื• ื˜ืึธืŸ ื“ืึธืก, ืžื™ืจ ื ื•ืฆืŸ ื“ื™ json ืžื•ืกื˜ืขืจ ืคื•ืŸ ื“ื™ ืจืขืœืก ื›ื™ื™ืคืขืฅ:

{
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": ${layersSizes[$i]},
         "digest": "sha256:${layersNames[$i]}"
      },

ืžื™ืจ ื•ื•ืขืœืŸ ืœื™ื™ื’ืŸ ืขืก ืฆื• ื“ื™ ืžืึทื ืึทืคืขืกื˜ื™ื™ืฉืึทืŸ ืคึฟืึทืจ ื™ืขื“ืขืจ ืจืขืœืก.

ื“ืขืจื ืึธืš, ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื’ืขืคึฟื™ื ืขืŸ ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ืงืึธื ืคื™ื’ ื˜ืขืงืข ืื•ืŸ ืคืึทืจื‘ื™ื™ึทื˜ืŸ ื“ื™ ืกื˜ืึทื‘ืก ืื™ืŸ ื“ื™ ื‘ืึทืฉื™ื™ึทืžืคึผืขืจืœืขืš ืžื™ื˜ ืคืึทืงื˜ื™ืฉ ื“ืึทื˜ืŸ

sed -i "s/config_size/$configSize/g; s/config_hash/$configName/g" $manifestFile

ืื™ืฆื˜ ืื™ืจ ืงืขื ืขืŸ ืึธื ื”ื™ื™ื‘ืŸ ื“ื™ ืืจืืคืงืืคื™ืข ืคึผืจืึธืฆืขืก ืื•ืŸ ืจืึทื˜ืขื•ื•ืขืŸ ื–ื™ืš ืึท ื•ื•ื™ื“, ื•ื•ืึธืก ื–ืึธืœ ื‘ืึทื’ืœื™ื™ื˜ืŸ ืึทืœืข ืกืึทื‘ืกืึทืงื•ื•ืึทื ื˜ ืจื™ืงื•ื•ืขืก.

ื“ืขืจ ื’ืึทื ืฅ ืฉืจื™ืคื˜ ืงื•ืงื˜ ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก:

#!/bin/bash -eux

imageDir=$1
# url as http://localhost:8081/link/to/docker/registry
url=$2
repoName=$3
tag=$4
manifestFile=$(readlink -f ${imageDir}/manifestCopy)
configFile=$(readlink -f $(find $imageDir -name "*.json" ! -name "manifest.json"))

# calc layers sha 256 sum, rename them accordingly, and add info about each to manifest file
function prepareLayersForUpload() {
  info_file=$imageDir/info
  # lets calculate layers sha256 and use it as layers names further
  layersNames=($(find $imageDir -name "layer.tar" -exec shasum -a 256 {} ; | cut -d" " -f1))

  # rename layers according to shasums. !!!Set required amount of fields for cut command!!!
  # this part definitely can be done easier but i didn't found another way, sry
  find $imageDir -name "layer.tar" -exec bash -c 'mv {} "$(echo {} | cut -d"/" -f1,2)/$(shasum -a 256 {} | cut -d" " -f1)"' ;

  layersSizes=($(find $imageDir -name "*.tar" -exec ls -l {} ; | awk '{print $5}'))

  for i in "${!layersNames[@]}"; do
    echo "{
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": ${layersSizes[$i]},
         "digest": "sha256:${layersNames[$i]}"
      }," >> $manifestFile
  done
  # remove last ','
  truncate -s-2 $manifestFile
  # add closing brakets to keep json consistent
  printf "nt]n}" >> $manifestFile
}

# calc config sha 256 sum and add info about it to manifest
function setConfigProps() {
  configSize=$(ls -l $configFile | awk '{print $5}')
  configName=$(basename $configFile | cut -d"." -f1)

  sed -i "s/config_size/$configSize/g; s/config_hash/$configName/g" $manifestFile
}

#prepare manifest file
prepareLayersForUpload
setConfigProps
cat $manifestFile

# initiate upload and get uuid
uuid=$(curl -s -X POST -I "$url/v2/$repoName/blobs/uploads/" | grep -oP "(?<=Docker-Upload-Uuid: ).+")

# patch layers
# in data-binary we're getting absolute path to layer file
for l in "${!layersNames[@]}"; do
  pathToLayer=$(find $imageDir -name ${layersNames[$l]} -exec readlink -f {} ;)
    curl -v -X PATCH "$url/v2/$repoName/blobs/uploads/$uuid" 
  -H "Content-Length: ${layersSizes[$i]}" 
  -H "Content-Type: application/octet-stream" 
  --data-binary "@$pathToLayer"

# put layer
  curl -v -X PUT "$url/v2/$repoName/blobs/uploads/$uuid?digest=sha256:${layersNames[$i]}" 
  -H 'Content-Type: application/octet-stream' 
  -H "Content-Length: ${layersSizes[$i]}" 
  --data-binary "@$pathToLayer"
done

# patch and put config after all layers
curl -v -X PATCH "$url/v2/$repoName/blobs/uploads/$uuid" 
  -H "Content-Length: $configSize" 
  -H "Content-Type: application/octet-stream" 
  --data-binary "@$configFile"

  curl -v -X PUT "$url/v2/$repoName/blobs/uploads/$uuid?digest=sha256:$configName" 
  -H 'Content-Type: application/octet-stream' 
  -H "Content-Length: $configSize" 
  --data-binary "@$configFile"

# put manifest
curl -v -X PUT "$url/v2/$repoName/manifests/$tag" 
  -H 'Content-Type: application/vnd.docker.distribution.manifest.v2+json' 
  --data-binary "@$manifestFile"

exit 0

ืžื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ืึท ืคืึทืจื˜ื™ืง ืฉืจื™ืคื˜:

./uploadImage.sh "~/path/to/saved/image" "http://localhost:8081/link/to/docker/registry" myRepoName 1.0

UPD:
ื•ื•ืึธืก ื”ืึธื‘ืŸ ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜?
ืคื™ืจืกื˜ืœื™, ืคืึทืงื˜ื™ืฉ ื“ืึทื˜ืŸ ืคึฟืึทืจ ืึทื ืึทืœื™ืกื™ืก, ื–ื™ื ื˜ ื“ื™ ื˜ืขืกืฅ ื–ืขื ืขืŸ ืœื•ื™ืคืŸ ืื™ืŸ ื‘ืœืึทื–ืขืžืขื˜ืขืจ ืื•ืŸ ื“ื™ ื“ืึทื˜ืŸ ืื•ื™ืฃ ื“ืึธืงืงืขืจ ืงืœื™ืขื ื˜ ืจื™ืงื•ื•ืขืก ื–ืขื ืขืŸ ื ื™ืฉื˜ ื–ื™ื™ืขืจ ื™ื ืคืึธืจืžืึทื˜ื™ื•ื•, ื ื™ื˜ ืขื ืœืขืš ืจื™ื™ืŸ ื”ื˜ื˜ืคึผ ืจื™ืงื•ื•ืขืก.

ืฆื•ื•ื™ื™ื˜ื ืก, ื“ื™ ื™ื‘ืขืจื’ืึทื ื’ ืขืจืœื•ื™ื‘ื˜ ืื•ื ื“ื– ืฆื• ืคืึทืจื’ืจืขืกืขืจืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ื•ื•ื™ืจื˜ื•ืึทืœ ื™ื•ื–ืขืจื– ืคึฟืึทืจ ื“ืึธืงืงืขืจ ื•ืคึผืœืึธืึทื“ ืžื™ื˜ ื•ื•ืขื’ืŸ 150% ืื•ืŸ ื‘ืึทืงื•ืžืขืŸ ืึท ื“ื•ืจื›ืฉื ื™ื˜ืœืขืš ืขื ื˜ืคืขืจ ืฆื™ื™ื˜ 20-25% ืคืึทืกื˜ืขืจ. ืคึฟืึทืจ ื“ืึทืงืขืจ ืืจืืคืงืืคื™ืข, ืžื™ืจ ื’ืขืจืื˜ืŸ ืฆื• ืคืึทืจื’ืจืขืกืขืจืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ื™ื•ื–ืขืจื– ืžื™ื˜ 500%, ื‘ืฉืขืช ื“ื™ ื“ื•ืจื›ืฉื ื™ื˜ืœืขืš ืขื ื˜ืคืขืจ ืฆื™ื™ื˜ ืื™ื– ืจื™ื“ื•ืกื˜ ืžื™ื˜ ื•ื•ืขื’ืŸ 60%.

ื“ืื ืง ืื™ืจ ืคึฟืึทืจ ืื™ื™ืขืจ ื•ืคืžืขืจืงื–ืึทืžืงื™ื™ึทื˜.

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’