HTTP рд╡рд┐рдирдВрддреНрдпрд╛ рд╡рд╛рдкрд░реВрди рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░ рдкреБрд▓ рдЖрдгрд┐ рдбреЙрдХрд░ рдкреБрд╢ рдХрдорд╛рдВрдбрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░рдгреЗ

рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдЧрд╡рддрд╛рдЪреНрдпрд╛ 2 рдкрд┐рд╢рд╡реНрдпрд╛, 75 рдореЗрд╕реНрдХрд▓рд╛рдЗрди рдЯреЕрдмреНрд▓реЗрдЯ рдпреБрдирд┐рдХреНрд╕ рд╡рд╛рддрд╛рд╡рд░рдг, рдПрдХ рдбреЙрдХрд░ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдЖрдгрд┐ рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░ рдкреБрд▓ рдЖрдгрд┐ рдбреЙрдХрд░ рдкреБрд╢ рдХрдорд╛рдВрдбрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░рдгреНрдпрд╛рдЪреЗ рдХрд╛рд░реНрдп рд╣реЛрддреЗ.

HTTP рд╡рд┐рдирдВрддреНрдпрд╛ рд╡рд╛рдкрд░реВрди рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░ рдкреБрд▓ рдЖрдгрд┐ рдбреЙрдХрд░ рдкреБрд╢ рдХрдорд╛рдВрдбрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░рдгреЗ

рдпреВрдкреАрдПрд╕:
рдкреНрд░рд╢реНрди: рд╣реЗ рд╕рд░реНрд╡ рдХрд╢рд╛рд╕рд╛рдареА рдЖрд╣реЗ?
рдЙрддреНрддрд░: рдЙрддреНрдкрд╛рджрдирд╛рдЪреА рд▓реЛрдб рдЪрд╛рдЪрдгреА (рдмреЕрд╢ рд╡рд╛рдкрд░рдд рдирд╛рд╣реА, рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╢реИрдХреНрд╖рдгрд┐рдХ рд╣реЗрддреВрдВрд╕рд╛рдареА рдкреНрд░рджрд╛рди рдХреЗрд▓реНрдпрд╛ рдЖрд╣реЗрдд). рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрддрд░ (рд╡рд╛рдЬрд╡реА рдорд░реНрдпрд╛рджреЗрдд) рдХрдореА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рддреНрдпрд╛рдиреБрд╕рд╛рд░, рдЙрдЪреНрдЪ рднрд╛рд░рд╛рдЪреЗ рдЕрдиреБрдХрд░рдг рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрдЪрд╛ рд╡рд╛рдкрд░ рди рдХрд░рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрдгреНрдпрд╛рдд рдЖрд▓рд╛. рдкрд░рд┐рдгрд╛рдореА, рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрдЪреЗ рд╕рд░реНрд╡ рд╕рд┐рд╕реНрдЯрдо рд╡рд┐рд▓рдВрдм рдХрд╛рдврд▓реЗ рдЧреЗрд▓реЗ. рдЖрдореНрд╣рд╛рд▓рд╛ рдереЗрдЯ рдЙрддреНрдкрд╛рджрдирд╛рд╡рд░ рддреБрд▓рдиреЗрдиреЗ рд╕реНрд╡рдЪреНрдЫ рднрд╛рд░ рдорд┐рд│рд╛рд▓рд╛.
рд▓реЗрдЦрд╛рдд рд╕рд╛рдзрдирд╛рдВрдЪреНрдпрд╛ GNU рдЖрд╡реГрддреНрддреНрдпрд╛ рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЖрд╣реЗрдд.

рдкреНрд░рдердо, рдпрд╛ рдЖрдЬреНрдЮрд╛ рдХрд╛рдп рдХрд░рддрд╛рдд рддреЗ рд╢реЛрдзреВрдпрд╛.

рддрд░ рдбреЙрдХрд░ рдкреБрд▓ рдХрд╢рд╛рд╕рд╛рдареА рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рддреЛ? рддреНрдпрд╛рдиреБрд╕рд╛рд░ рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг:

"рд░реЗрдЬрд┐рд╕реНрдЯреНрд░реАрдордзреВрди рдкреНрд░рддрд┐рдорд╛ рдХрд┐рдВрд╡рд╛ рднрд╛рдВрдбрд╛рд░ рдХрд╛рдврд╛".

рддреЗрдереЗ рдЖрдореНрд╣рд╛рд▓рд╛ рдПрдХ рд▓рд┐рдВрдХ рджреЗрдЦреАрд▓ рдорд┐рд│рддреЗ рдкреНрд░рддрд┐рдорд╛, рдХрдВрдЯреЗрдирд░ рдЖрдгрд┐ рд╕реНрдЯреЛрд░реЗрдЬ рдбреНрд░рд╛рдпрд╡реНрд╣рд░реНрд╕ рд╕рдордЬреВрди рдШреНрдпрд╛.

HTTP рд╡рд┐рдирдВрддреНрдпрд╛ рд╡рд╛рдкрд░реВрди рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░ рдкреБрд▓ рдЖрдгрд┐ рдбреЙрдХрд░ рдкреБрд╢ рдХрдорд╛рдВрдбрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░рдгреЗ

рдпреЗрдереВрди рдЖрдкрдг рд╕рдордЬреВ рд╢рдХрддреЛ рдХреА рдбреЙрдХрд░ рдкреНрд░рддрд┐рдорд╛ рд╣реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрддрд░рд╛рдВрдЪрд╛ рдПрдХ рд╕рдВрдЪ рдЖрд╣реЗ рдЬреНрдпрд╛рдордзреНрдпреЗ рдкреНрд░рддрд┐рдореЗрддреАрд▓ рдирд╡реАрдирддрдо рдмрджрд▓рд╛рдВрдмрджреНрджрд▓ рдорд╛рд╣рд┐рддреА рдЕрд╕рддреЗ, рдЬреА рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдкреБрдвреЗ рдЖрдкрдг рдкрд╛рд╣рддреЛ рдиреЛрдВрджрдгреА API.

рд╣реЗ рдЦрд╛рд▓реАрд▓ рдореНрд╣рдгрддреЗ:

"рдПрдХ "рдЗрдореЗрдЬ" рд╣реЗ 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 рд╡рд┐рдирдВрддреНрдпрд╛ рд╡рд╛рдкрд░реВрди рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрд╢рд┐рд╡рд╛рдп рдбреЙрдХрд░ рдкреБрд▓ рдЖрдгрд┐ рдбреЙрдХрд░ рдкреБрд╢ рдХрдорд╛рдВрдбрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░рдгреЗ

рдкреНрд░рддрд┐рд╕рд╛рджрд╛рдд, рдЖрдореНрд╣рд╛рд▓рд╛ json рдкреНрд░рд╛рдкреНрдд рд╣реЛрддреЛ рдЬреНрдпрд╛рддреВрди рдЖрдореНрд╣рд╛рд▓рд╛ рд╕рдзреНрдпрд╛ рдлрдХреНрдд рд▓рд╛рдЗрдлрд▓рд╛рдЗрдирдордзреНрдпреЗ рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рдРрд╡рдЬреА рддреНрдпрд╛рдВрдЪреНрдпрд╛ рд╣реЕрд╢рдордзреНрдпреЗ рд░рд╕ рдЖрд╣реЗ. рддреЗ рдорд┐рд│рд╛рд▓реНрдпрд╛рдирдВрддрд░, рдЖрдореНрд╣реА рдкреНрд░рддреНрдпреЗрдХрд╛рдХрдбреЗ рдЬрд╛рдК рд╢рдХрддреЛ рдЖрдгрд┐ рдкреБрдвреАрд▓ рд╡рд┐рдирдВрддреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░реВ рд╢рдХрддреЛ: "GET /v2/{name}/blobs/{digest}"

"рд▓реЗрдпрд░рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рд░реЗрдкреЙрдЬрд┐рдЯрд░реАрдЪреНрдпрд╛ рдирд╛рд╡рд╛рдиреЗ рдХреЗрд▓рд╛ рдЬрд╛рдИрд▓ рдкрд░рдВрддреБ рдбрд╛рдпрдЬреЗрд╕реНрдЯрджреНрд╡рд╛рд░реЗ рд░реЗрдЬрд┐рд╕реНрдЯреНрд░реАрдордзреНрдпреЗ рдЕрджреНрд╡рд┐рддреАрдпрдкрдгреЗ рдУрд│рдЦрд▓рд╛ рдЬрд╛рдИрд▓."

рдпрд╛ рдкреНрд░рдХрд░рдгрд╛рдд рдбрд╛рдпрдЬреЗрд╕реНрдЯ рд╣рд╛ рд╣реЕрд╢ рдЖрд╣реЗ рдЬреЛ рдЖрдореНрд╣рд╛рд▓рд╛ рдкреНрд░рд╛рдкреНрдд рдЭрд╛рд▓рд╛ рдЖрд╣реЗ.

рдкреНрд░рдпрддреНрди рдХрд░рдд рдЖрд╣реЗ

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

рднрд╛рдЧ реи - рдбреЙрдХрд░ рдкреБрд╢

рд╣реЗ рдереЛрдбреЗ рдЕрдзрд┐рдХ рдХреНрд▓рд┐рд╖реНрдЯ рд╣реЛрдИрд▓.

рдЪрд▓рд╛ рдкреБрдиреНрд╣рд╛ рд╕реБрд░реБрд╡рд╛рдд рдХрд░реВрдпрд╛ рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг. рдореНрд╣рдгреВрди рдЖрдореНрд╣рд╛рд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ рдиреЗрддрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ, рд╕рдВрдмрдВрдзрд┐рдд рдореЕрдирд┐рдлреЗрд╕реНрдЯ рдЧреЛрд│рд╛ рдХрд░рдгреЗ рдЖрдгрд┐ рддреЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдгреЗ рджреЗрдЦреАрд▓ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рд╣реЗ рд╕реЛрдкреЗ рджрд┐рд╕рддреЗ.

рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдгрд╛рдЪрд╛ рдЕрднреНрдпрд╛рд╕ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рдЖрдореНрд╣реА рдбрд╛рдЙрдирд▓реЛрдб рдкреНрд░рдХреНрд░рд┐рдпреЗрд▓рд╛ рдЕрдиреЗрдХ рдЪрд░рдгрд╛рдВрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЧреВ рд╢рдХрддреЛ:

  • рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЖрд░рдВрдн - "POST /v2/{repoName}/blobs/uploads/"
  • рд▓рд╛рдЗрдлрд▓рд╛рдЗрди рдЕрдкрд▓реЛрдб рдХрд░рдд рдЖрд╣реЗ (рдЖрдореНрд╣реА рдореЛрдиреЛрд▓рд┐рдерд┐рдХ рдЕрдкрд▓реЛрдб рд╡рд╛рдкрд░реВ, рдореНрд╣рдгрдЬреЗ рдЖрдореНрд╣реА рдкреНрд░рддреНрдпреЗрдХ рд▓рд╛рдИрдлрд▓рд╛рдИрди рд╕рдВрдкреВрд░реНрдгрдкрдгреЗ рдкрд╛рдард╡рддреЛ) - "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
    рд╕рд╛рдордЧреНрд░реА-рд▓рд╛рдВрдмреА: {рд╕реНрддрд░рд╛рдЪрд╛ рдЖрдХрд╛рд░}
    рд╕рд╛рдордЧреНрд░реА-рдкреНрд░рдХрд╛рд░: рдЕрдиреБрдкреНрд░рдпреЛрдЧ/рдСрдХреНрдЯреЗрдЯ-рд╕реНрдЯреНрд░реАрдо
    рд▓реЗрдпрд░ рдмрд╛рдпрдирд░реА рдбреЗрдЯрд╛".
  • рдореЕрдирд┐рдлреЗрд╕реНрдЯ рд▓реЛрдб рдХрд░рдд рдЖрд╣реЗ - "PUT /v2/{repoName}/manifests/{reference}".

рдкрд░рдВрддреБ рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг рдПрдХ рдкрд╛рдКрд▓ рдЪреБрдХрддреЗ, рддреНрдпрд╛рд╢рд┐рд╡рд╛рдп рдХрд╛рд╣реАрд╣реА рдХрд╛рд░реНрдп рдХрд░рдгрд╛рд░ рдирд╛рд╣реА. рдореЛрдиреЛрд▓рд┐рдерд┐рдХ рд▓реЛрдбрд┐рдВрдЧрд╕рд╛рдареА, рддрд╕реЗрдЪ рдЖрдВрд╢рд┐рдХ (рдЦрдВрдбрд┐рдд) рд╕рд╛рдареА, рд░реЗрд▓ рд▓реЛрдб рдХрд░рдгреНрдпрд╛рдкреВрд░реНрд╡реА, рддреБрдореНрд╣реА рдкреЕрдЪ рд╡рд┐рдирдВрддреА рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

"рдкреЕрдЯрдЪ /v2/{repoName}/blobs/uploads/{uuid}
рд╕рд╛рдордЧреНрд░реА-рд▓рд╛рдВрдмреА: {рдЦрдВрдбрд╛рдЪрд╛ рдЖрдХрд╛рд░}
рд╕рд╛рдордЧреНрд░реА-рдкреНрд░рдХрд╛рд░: рдЕрдиреБрдкреНрд░рдпреЛрдЧ/рдСрдХреНрдЯреЗрдЯ-рд╕реНрдЯреНрд░реАрдо
{рд▓реЗрдпрд░ рдЪрдВрдХ рдмрд╛рдпрдирд░реА рдбреЗрдЯрд╛}".

рдЕрдиреНрдпрдерд╛, рддреБрдореНрд╣реА рдкрд╣рд┐рд▓реНрдпрд╛ рдмрд┐рдВрджреВрдЪреНрдпрд╛ рдкреБрдвреЗ рдЬрд╛рдК рд╢рдХрдгрд╛рд░ рдирд╛рд╣реА, рдХрд╛рд░рдг... рдЕрдкреЗрдХреНрд╖рд┐рдд рдкреНрд░рддрд┐рд╕рд╛рдж рдХреЛрдб 202 рдРрд╡рдЬреА, рддреБрдореНрд╣рд╛рд▓рд╛ 4xx рдкреНрд░рд╛рдкреНрдд рд╣реЛрдИрд▓.

рдЖрддрд╛ рдЕрд▓реНрдЧреЛрд░рд┐рджрдо рдЕрд╕реЗ рджрд┐рд╕рддреЗ:

  • рдЖрд░рдВрдн
  • рдкреЕрдЪ рд░реЗрд▓реНрд╡реЗ
  • рд░реЗрд▓рд┐рдВрдЧ рд▓реЛрдб рдХрд░рдд рдЖрд╣реЗ
  • рдореЕрдирд┐рдлреЗрд╕реНрдЯ рд▓реЛрдб рдХрд░рдд рдЖрд╣реЗ
    рдмрд┐рдВрджреВ 2 рдЖрдгрд┐ 3, рдЕрдиреБрдХреНрд░рдореЗ, рдЬрд┐рддрдХреНрдпрд╛ рд╡реЗрд│рд╛ рдУрд│реА рд▓реЛрдб рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рддрд┐рддрдХреНрдпрд╛ рд╡реЗрд│рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддреА рд╣реЛрдИрд▓.

рдкреНрд░рдердо, рдЖрдореНрд╣рд╛рд▓рд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА рдкреНрд░рддрд┐рдореЗрдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ. рдореА archlinux:latest рд╡рд╛рдкрд░реЗрди

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

рдЖрддрд╛ рддреБрдореНрд╣реА рдбрд╛рдЙрдирд▓реЛрдб рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реБрд░реВ рдХрд░реВ рд╢рдХрддрд╛ рдЖрдгрд┐ рд╕реНрд╡рдд:рд▓рд╛ рдПрдХ uuid рдЬрддрди рдХрд░реВ рд╢рдХрддрд╛, рдЬреЗ рддреНрдпрд╛рдирдВрддрд░рдЪреНрдпрд╛ рд╕рд░реНрд╡ рд╡рд┐рдирдВрддреНрдпрд╛рдВрд╕реЛрдмрдд рдЕрд╕рд╛рд╡реЗ.

рд╕рдВрдкреВрд░реНрдг рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдпрд╛рд╕рд╛рд░рдЦреЗ рдХрд╛рд╣реАрддрд░реА рджрд┐рд╕рддреЗ:

#!/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

рдпреВрдкреАрдПрд╕:
рдкрд░рд┐рдгрд╛рдореА рдЖрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рдорд┐рд│рд╛рд▓реЗ?
рдкреНрд░рдердо, рд╡рд┐рд╢реНрд▓реЗрд╖рдгрд╛рд╕рд╛рдареА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛, рдХрд╛рд░рдг рдЪрд╛рдЪрдгреНрдпрд╛ рдмреНрд▓реЗрдЭрдореАрдЯрд░рдордзреНрдпреЗ рдЪрд╛рд▓рд╡рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд рдЖрдгрд┐ рдбреЙрдХрд░ рдХреНрд▓рд╛рдпрдВрдЯрдЪреНрдпрд╛ рд╡рд┐рдирдВрддреНрдпрд╛рдВрд╡рд░реАрд▓ рдбреЗрдЯрд╛ рд╢реБрджреНрдз HTTP рд╡рд┐рдирдВрддреНрдпрд╛рдВрдкреНрд░рдорд╛рдгреЗ рдлрд╛рд░рд╕рд╛ рдорд╛рд╣рд┐рддреАрдкреВрд░реНрдг рдирд╕рддреЛ.

рджреБрд╕рд░реЗ рдореНрд╣рдгрдЬреЗ, рд╕рдВрдХреНрд░рдордгрд╛рдиреЗ рдЖрдореНрд╣рд╛рд▓рд╛ рдбреЙрдХрд░ рдЕрдкрд▓реЛрдбрд╕рд╛рдареА рд╡реНрд╣рд░реНрдЪреНрдпреБрдЕрд▓ рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдВрдЪреА рд╕рдВрдЦреНрдпрд╛ рд╕реБрдорд╛рд░реЗ 150% рдиреЗ рд╡рд╛рдврд╡рдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рд╕рд░рд╛рд╕рд░реА рдкреНрд░рддрд┐рд╕рд╛рдж рд╡реЗрд│ 20-25% рдЬрд▓рдж рдорд┐рд│рд╡рд┐рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджрд┐рд▓реА. рдбреЙрдХрд░ рдбрд╛рдЙрдирд▓реЛрдбрд╕рд╛рдареА, рдЖрдореНрд╣реА рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдВрдЪреА рд╕рдВрдЦреНрдпрд╛ 500% рд╡рд╛рдврд╡рд┐рдгреНрдпрд╛рдд рд╡реНрдпрд╡рд╕реНрдерд╛рдкрд┐рдд рдХреЗрд▓реЗ, рддрд░ рд╕рд░рд╛рд╕рд░реА рдкреНрд░рддрд┐рд╕рд╛рдж рд╡реЗрд│ рд╕реБрдорд╛рд░реЗ 60% рдиреЗ рдХрдореА рдЭрд╛рд▓рд╛.

рдЖрдкрд▓реНрдпрд╛ рд▓рдХреНрд╖ рджрд┐рд▓реНрдпрд╛рдмрджреНрджрд▓ рдзрдиреНрдпрд╡рд╛рдж.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛