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

เชญเชพเช— 2 - เชกเซ‹เช•เชฐ เชชเซเชถ

เช† เชฅเซ‹เชกเซ€ เชตเชงเซ เชœเชŸเชฟเชฒ เชนเชถเซ‡.

เชธเชพเชฅเซ‡ เชซเชฐเซ€ เชถเชฐเซ‚ เช•เชฐเซ€เช เชฆเชธเซเชคเชพเชตเซ‡เชœเซ€เช•เชฐเชฃ. เชคเซ‡เชฅเซ€ เช†เชชเชฃเซ‡ เชฆเชฐเซ‡เช• เชฒเซ€เชกเชฐเชจเซ‡ เชกเชพเช‰เชจเชฒเซ‹เชก เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡, เช…เชจเซเชฐเซ‚เชช เชฎเซ‡เชจเชฟเชซเซ‡เชธเซเชŸ เชเช•เชคเซเชฐเชฟเชค เช•เชฐเซ‹ เช…เชจเซ‡ เชคเซ‡เชจเซ‡ เชชเชฃ เชกเชพเช‰เชจเชฒเซ‹เชก เช•เชฐเซ‹. เชคเซ‡ เชธเชฐเชณ เชฒเชพเช—เซ‡ เช›เซ‡.

เชฆเชธเซเชคเชพเชตเซ‡เชœเซ‹เชจเซ‹ เช…เชญเซเชฏเชพเชธ เช•เชฐเซเชฏเชพ เชชเช›เซ€, เช…เชฎเซ‡ เชกเชพเช‰เชจเชฒเซ‹เชก เชชเซเชฐเช•เซเชฐเชฟเชฏเชพเชจเซ‡ เช•เซ‡เชŸเชฒเชพเช• เชชเช—เชฒเชพเช“เชฎเชพเช‚ เชตเชฟเชญเชพเชœเชฟเชค เช•เชฐเซ€ เชถเช•เซ€เช เช›เซ€เช:

  • เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช†เชฐเช‚เชญ - "POST /v2/{repoName}/blobs/uploads/"
  • เชฒเชพเช‡เชซเชฒเชพเช‡เชจ เช…เชชเชฒเซ‹เชก เช•เชฐเชตเซ€ (เช…เชฎเซ‡ เชเช• เชฎเซ‹เชจเซ‹เชฒเชฟเชฅเชฟเช• เช…เชชเชฒเซ‹เชกเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชถเซเช‚, เชเชŸเชฒเซ‡ เช•เซ‡ เช…เชฎเซ‡ เชฆเชฐเซ‡เช• เชฒเชพเช‡เชซเชฒเชพเช‡เชจเชจเซ‡ เชคเซ‡เชจเซ€ เชธเช‚เชชเซ‚เชฐเซเชฃเชคเชพเชฎเชพเช‚ เชฎเซ‹เช•เชฒเซ€เชถเซเช‚) - "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
    เชธเชพเชฎเช—เซเชฐเซ€-เชฒเช‚เชฌเชพเชˆ: {เชธเซเชคเชฐเชจเซเช‚ เช•เชฆ}
    เชธเชพเชฎเช—เซเชฐเซ€-เชชเซเชฐเช•เชพเชฐ: เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ/เช“เช•เซเชŸเซ‡เชŸ-เชธเซเชŸเซเชฐเซ€เชฎ
    เชฒเซ‡เชฏเชฐ เชฌเชพเชˆเชจเชฐเซ€ เชกเซ‡เชŸเชพ"
  • เชฎเซ‡เชจเชฟเชซเซ‡เชธเซเชŸ เชฒเซ‹เชก เช•เชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡ - "PUT /v2/{repoName}/manifests/{reference}".

เชชเชฐเช‚เชคเซ เชฆเชธเซเชคเชพเชตเซ‡เชœเซ€เช•เชฐเชฃ เชเช• เชชเช—เชฒเซเช‚ เชšเซ‚เช•เซ€ เชœเชพเชฏ เช›เซ‡, เชœเซ‡เชจเชพ เชตเชฟเชจเชพ เช•เช‚เชˆเชชเชฃ เช•เชพเชฎ เช•เชฐเชถเซ‡ เชจเชนเซ€เช‚. เชฎเซ‹เชจเซ‹เชฒเชฟเชฅเชฟเช• เชฒเซ‹เชกเชฟเช‚เช— เชฎเชพเชŸเซ‡, เชคเซ‡เชฎเชœ เช†เช‚เชถเชฟเช• (เชšเช‚เช•เซเชก) เชฎเชพเชŸเซ‡, เชฐเซ‡เชฒ เชฒเซ‹เชก เช•เชฐเชคเชพ เชชเชนเซ‡เชฒเชพ, เชคเชฎเชพเชฐเซ‡ เชชเซ‡เชš เชตเชฟเชจเช‚เชคเซ€ เช•เชฐเชตเซ€ เช†เชตเชถเซเชฏเช• เช›เซ‡:

"PATCH /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 (เชฒเซ‡เช–เชจ เชธเชฎเชฏเซ‡ เชตเชฐเซเชคเชฎเชพเชจ), เชฎเซ€เชกเชฟเชฏเชพ เชชเซเชฐเช•เชพเชฐ เชฏเชฅเชพเชตเชค เชฐเชพเช–เชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡:

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

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹