ืืืจ ืืึธืื 2 ืืึทืืก ืคืื ืืจืึธื, 75 ืืขืกืงืึทืืื ืข ืืึทืืืึทืฅ ืืื ืืงืก ืกืืืืืืข, ืึท ืืึธืงืงืขืจ ืจืืคึผืึทืืึทืืึธืจื ืืื ืื ืึทืจืืขื ืคืื ืืืคึผืืึทืืขื ืื ื ืื ืืึทืงืขืจ ืฆืืขื ืืื ืืึทืงืขืจ ืฉืืืคึผื ืงืึทืืึทื ืื ืึธื ืึท ืืึธืงืงืขืจ ืงืืืขื ื.
UPD:
ืคืจืืืข: ืืืึธืก ืืื ืืึธืก ืึทืืข ืคึฟืึทืจ?
ืขื ืืคืขืจ: ืืึทืกืข ืืขืกืืื ื ืคืื ืื ืคึผืจืึธืืืงื (ื ืืฉื ื ืืฆื ืืึทืฉ, ืื ืกืงืจืืคึผืก ืืขื ืขื ืฆืืืขืฉืืขืื ืคึฟืึทืจ ืืืืืื ืืงืจืืื ืฆืืืขืงื). ืขืก ืืื ืืึทืฉืืึธืกื ื ืืฉื ืฆื ื ืืฆื ืื ืืึธืงืงืขืจ ืงืืืขื ื ืฆื ืจืขืืืฆืืจื ื ืึธื ืืืึทืขืจืก (ืืื ืืืืึทื ืืืืึทืฅ) ืืื, ืึทืงืึธืจืืื ืืื, ืขืืืึทืืืื ืึท ืืขืืขืจ ืืึทืกืข. ืืื ืึท ืจืขืืืืืึทื, ืึทืืข ืกืืกืืขื ืืืืืื ืคืื ืื ืืึธืงืงืขืจ ืงืืืขื ื ืืขื ืขื ืึทืืืขืงืืขื ืืืขื. ืืืจ ืืืงืืืขื ืึท ืืขืคืืขืจืขื ืจืืื ืืึทืกืข ืืืืึทื ืืืืฃ ืืขื ืคึผืจืึธืืืงื.
ืืขืจ ืึทืจืืืงื ืืขืืืืื ื GNU ืืืขืจืกืืขืก ืคืื ืืืฉืืจืื.
ืขืจืฉืืขืจ, ืืึธืื ืก ืจืขืืขื ืขื ืืืืก ืืืึธืก ืื ืงืึทืืึทื ืื ืืึธื.
ืึทืืื ืืืึธืก ืืื ืืึธืงืขืจ ืฆืืขื ืืขื ืืฆื ืคึฟืึทืจ? ืืืื
"ืฆืืขื ืึท ืืืื ืึธืืขืจ ืึท ืจืืคึผืึทืืึทืืึธืจื ืคืื ืึท ืจืขืืืกืืจื".
ืืึธ ืืืจ ืืืื ืืขืคึฟืื ืขื ืึท ืืื ืง ืฆื
ืคืื ืืึธ ืืืจ ืงืขื ืขื ืคึฟืึทืจืฉืืืื ืึทื ืึท ืืึธืงืงืขืจ ืืืื ืืื ืึท ืกืืื ืคืื ืืืืขืจ ืืืึทืขืจืก ืืืึธืก ืึทื ืืืึทืืื ืืื ืคึฟืึธืจืืึทืฆืืข ืืืขืื ืื ืืขืฆืืข ืขื ืืขืจืื ืืขื ืืื ืื ืืืื, ืืืึธืก ืืื ืืึธื ืืืึธืก ืืืจ ืืึทืจืคึฟื. ืืืืึทืืขืจ ืืืจ ืงืืงื ืืื
ืขืก ืืืื ืื ืคืืืืขื ืืข:
"ื "ืืืื" ืืื ืึท ืงืึธืืืื ืึทืฆืืข ืคืื โโโโืึท 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"
ืืื ืขื ืืคืขืจ, ืืืจ ืืึทืงืืืขื ืืืฉืกืึธื ืคืื ืืืึธืก ืืืจ ืืขื ืขื ืืขืจืืืืึทื ืืืืื ืืื ืืขืจืขืกืืจื ืืื ืื ืืืืงืืืื ื, ืึธืืขืจ ืืึทื ืฅ ืืืืขืจ ืืึทืฉืขืก. ื ืึธื ืืืงืืืขื ืืื, ืืืจ ืงืขื ืขื ืืืื ืืืจื ืืขืืขืจ ืืืื ืขืจ ืืื ืืืกืคืืจื ืื ืคืืืืขื ืืข ืืขืื: "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
ืืึธืืืจ ืืขื ืืืึธืก ืคึฟืึทืจ ืึท ืืขืงืข ืืืจ ืืขืกืึธืฃ ืืืงืืืขื ืืื ืืขืจ ืขืจืฉืืขืจ ืืืืคืืืื.
file firstLayer
ืืขื ืข. ืจืืืื ืืขื ืขื ืืึทืจ ืึทืจืงืืืืื, ืึทื ืคึผืึทืงืื ื ืืื ืืื ืื ืฆืื ืขืืขื ืกืืจ ืืืจ ืืืขืื ืืึทืงืืืขื ืื ืืื ืืึทืื ืคืื ืื ืืืื.
ืืึธืืืจ ืฉืจืืึทืื ืึท ืงืืืื ืืึทืฉ ืฉืจืืคื ืึทืืื ืึทื ืึทืืข ืืขื ืงืขื ืขื ืืืื ืึธืืึทืืืืืื
#!/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
ืืืฆื ืืึธืื ืืื ืื ืจืึทืืขืืืขื ืขืก ืืึธืืงืึทืื ืคึฟืึทืจ ืืืืึทืืขืจ ืึทื ืึทืืืกืืก
docker save c24fe13d37b9 -o savedArch
ืื ืคึผืึทืง ืื ืจืืืึทืืืื ื ืึทืจืงืืืื ืืื ืื ืงืจืึทื ื ืืืขืืืืืึทืืขืจ
tar xvf savedArch
ืืื ืืืจ ืงืขื ืขื ืืขื, ืืขืืขืจ ืืืืคืืืื ืืื ืืื ืึท ืืึทืืื ืืขืจ ืืขืงืข. ืืืฆื ืืึธืืืจ ืงืืงื ืืื ืื ืกืืจืืงืืืจ ืคืื ืื ืืึทื ืึทืคืขืกืืืืฉืึทื ืืืึธืก ืืืจ ืืืงืืืขื
cat manifest.json | json_pp
ื ืืฉื ืืกืื. ืืื ืก ืืขื ืืืึธืก ืืึทื ืืคืขืกื ืืื ืืืจืฃ ืฆื ืืึทืกืข, ืืืื ืฆื
ืืึธื, ืื ืืืืืกืืื ื ืืึทื ืืคืขืกืืึธ ืืื ื ืืฉื ืคึผืึทืกืืง ืคึฟืึทืจ ืืื ืื, ืึทืืื ืืืจ ืืืขืื ืืึทืื ืืื ืืืขืจ ืืืืืขื ืข ืืื ืืืึทืงืืืฉืึทืง ืืื ืงืึธืืจืืืืึทื ืก, ืืืืคืืื ื ืืื ืงืึทื ืคืืืืขืจืืืฉืึทื ื.
ืืืจ ืืืขืื ืฉืืขื ืืืง ืืึธืื ืืืึท ืืื ืืกืืขืจ ืืืื ืงืึทื ืคืืืืขืจืืืฉืึทื ืืขืงืข ืืื ืึท ืืขื ืืข ืคืื โโืืืืคืืื ื. ืกืืขืืข ืืืขืจืกืืข 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