మాకు 2 బ్యాగ్ల గడ్డి, 75 మెస్కలైన్ టాబ్లెట్లు యునిక్స్ ఎన్విరాన్మెంట్, డాకర్ రిపోజిటరీ మరియు డాకర్ క్లయింట్ లేకుండా డాకర్ పుల్ మరియు డాకర్ పుష్ ఆదేశాలను అమలు చేసే పని ఉంది.
యుపిడి:
ప్రశ్న: ఇదంతా దేనికి?
సమాధానం: ఉత్పత్తి యొక్క లోడ్ పరీక్ష (బాష్ని ఉపయోగించడం లేదు, స్క్రిప్ట్లు విద్యా ప్రయోజనాల కోసం అందించబడ్డాయి). అదనపు లేయర్లను (సహేతుకమైన పరిమితుల్లో) తగ్గించడానికి డాకర్ క్లయింట్ని ఉపయోగించకూడదని నిర్ణయించబడింది మరియు తదనుగుణంగా, అధిక లోడ్ను అనుకరించండి. ఫలితంగా, డాకర్ క్లయింట్ యొక్క అన్ని సిస్టమ్ జాప్యాలు తీసివేయబడ్డాయి. మేము ఉత్పత్తిపై నేరుగా సాపేక్షంగా శుభ్రమైన లోడ్ను అందుకున్నాము.
వ్యాసం 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"
ప్రతిస్పందనగా, మేము 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
చివరకు మొదటి లైఫ్ లైన్ గా ఎలాంటి ఫైల్ అందుకున్నామో చూద్దాం.
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={digest}
కంటెంట్-పొడవు: {పొర పరిమాణం}
కంటెంట్-రకం: అప్లికేషన్/ఆక్టెట్ స్ట్రీమ్
లేయర్ బైనరీ డేటా". - మానిఫెస్ట్ను లోడ్ చేస్తోంది - "PUT /v2/{repoName}/manifests/{reference}".
కానీ డాక్యుమెంటేషన్ ఒక దశను కోల్పోతుంది, అది లేకుండా ఏమీ పని చేయదు. ఏకశిలా లోడింగ్ కోసం, అలాగే పాక్షిక (చంక్డ్) కోసం, రైలును లోడ్ చేయడానికి ముందు, మీరు తప్పనిసరిగా PATCH అభ్యర్థనను అమలు చేయాలి:
"PATCH /v2/{repoName}/blobs/uploads/{uuid}
కంటెంట్-నిడివి: {భాగం పరిమాణం}
కంటెంట్-రకం: అప్లికేషన్/ఆక్టెట్ స్ట్రీమ్
{లేయర్ చంక్ బైనరీ డేటా}".
లేకపోతే, మీరు మొదటి పాయింట్ను దాటి వెళ్లలేరు, ఎందుకంటే... ఊహించిన ప్రతిస్పందన కోడ్ 202కి బదులుగా, మీరు 4xxని అందుకుంటారు.
ఇప్పుడు అల్గోరిథం ఇలా కనిపిస్తుంది:
- ప్రారంభించడం
- ప్యాచ్ రైలు
- హ్యాండ్రైల్ను లోడ్ చేస్తోంది
- మానిఫెస్ట్ లోడ్ అవుతోంది
పాయింట్లు 2 మరియు 3, వరుసగా, లైన్ల సంఖ్యను లోడ్ చేయాల్సినన్ని సార్లు పునరావృతమవుతాయి.
మొదట, మనకు ఏదైనా చిత్రం అవసరం. నేను archlinux:latest ఉపయోగిస్తాను
docker pull archlinux
ఇప్పుడు తదుపరి విశ్లేషణ కోసం స్థానికంగా సేవ్ చేద్దాం
docker save c24fe13d37b9 -o savedArch
ఫలిత ఆర్కైవ్ను ప్రస్తుత డైరెక్టరీలోకి అన్ప్యాక్ చేయండి
tar xvf savedArch
మీరు చూడగలిగినట్లుగా, ప్రతి లైఫ్లైన్ ప్రత్యేక ఫోల్డర్లో ఉంటుంది. ఇప్పుడు మనం అందుకున్న మానిఫెస్ట్ యొక్క నిర్మాణాన్ని చూద్దాం
cat manifest.json | json_pp
ఎక్కువ కాదు. ప్రకారం, లోడ్ చేయడానికి మానిఫెస్ట్ ఏమి అవసరమో చూద్దాం
సహజంగానే, ఇప్పటికే ఉన్న మానిఫెస్టో మాకు సరిపోదు, కాబట్టి మేము బ్లాక్జాక్ మరియు వేశ్యలు, లైఫ్లైన్లు మరియు కాన్ఫిగర్లతో మా స్వంతం చేసుకుంటాము.
మేము ఎల్లప్పుడూ కనీసం ఒక కాన్ఫిగర్ ఫైల్ మరియు లైఫ్లైన్ల శ్రేణిని కలిగి ఉంటాము. స్కీమ్ వెర్షన్ 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