Mayroon kaming 2 bag ng damo, 75 mescaline tablets unix environment, isang docker repository at ang gawain ng pagpapatupad ng docker pull at docker push command nang walang docker client.
UPS:
Tanong: Para saan ang lahat ng ito?
Sagot: I-load ang pagsubok ng produkto (HINDI gumagamit ng bash, ang mga script ay ibinigay para sa mga layuning pang-edukasyon). Napagpasyahan na huwag gamitin ang docker client para bawasan ang mga karagdagang layer (sa loob ng makatwirang limitasyon) at, nang naaayon, tularan ang mas mataas na load. Bilang resulta, ang lahat ng mga pagkaantala sa system ng kliyente ng Docker ay inalis. Nakatanggap kami ng medyo malinis na pagkarga nang direkta sa produkto.
Gumamit ang artikulo ng mga bersyon ng GNU ng mga tool.
Una, alamin natin kung ano ang ginagawa ng mga utos na ito.
Kaya para saan ginagamit ang docker pull? Ayon kay
"Hilahin ang isang imahe o isang repository mula sa isang registry".
Doon din namin mahahanap ang isang link sa
Mula rito, mauunawaan natin na ang imahe ng docker ay isang hanay ng ilang mga layer na naglalaman ng impormasyon tungkol sa mga pinakabagong pagbabago sa larawan, na malinaw naman kung ano ang kailangan natin. Sunod naming tingnan
Sinasabi nito ang sumusunod:
"Ang isang "larawan" ay isang kumbinasyon ng isang JSON manifest at indibidwal na mga file ng layer. Ang proseso ng paghila ng isang > imahe ay nakasentro sa pagkuha ng dalawang bahaging ito."
Kaya ang unang hakbang ayon sa dokumentasyon ay "Pagkuha ng Image Manifest".
Siyempre, hindi namin ito kukunan, ngunit kailangan namin ang data mula dito. Ang sumusunod ay isang halimbawa ng kahilingan: GET /v2/{name}/manifests/{reference}
"Ang pangalan at reference na parameter ay tumutukoy sa larawan at kinakailangan. Ang reference ay maaaring may tag o digest."
Ang aming docker repository ay lokal na naka-deploy, subukan nating isagawa ang kahilingan:
curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/manifests/1.1.1" -H "header_if_needed"
Bilang tugon, natatanggap namin ang json kung saan kami ay kasalukuyang interesado lamang sa mga lifeline, o sa halip ang kanilang mga hash. Matapos matanggap ang mga ito, maaari nating suriin ang bawat isa at isakatuparan ang sumusunod na kahilingan: "GET /v2/{name}/blobs/{digest}"
"Ang pag-access sa isang layer ay lagyan ng gate ng pangalan ng repositoryo ngunit nakikilala sa natatanging registry sa pamamagitan ng digest."
digest sa kasong ito ay ang hash na natanggap namin.
Sinusubukan
curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/blobs/sha256:f972d139738dfcd1519fd2461815651336ee25a8b54c358834c50af094bb262f" -H "header_if_needed" --output firstLayer
Tingnan natin kung anong uri ng file ang sa wakas ay natanggap natin bilang unang lifeline.
file firstLayer
mga. Ang mga riles ay mga tar archive, ang pag-unpack ng mga ito sa naaangkop na pagkakasunud-sunod ay makukuha namin ang mga nilalaman ng imahe.
Sumulat tayo ng isang maliit na script ng bash upang ang lahat ng ito ay maging awtomatiko
#!/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
Ngayon ay maaari na nating patakbuhin ito gamit ang nais na mga parameter at makuha ang mga nilalaman ng kinakailangang imahe
./script.sh dirName βhttp://localhost:8081/link/to/docker/registryβ myAwesomeImage 1.0
Bahagi 2 - docker push
Ito ay magiging mas kumplikado ng kaunti.
Magsimula tayo muli sa
Pagkatapos pag-aralan ang dokumentasyon, maaari naming hatiin ang proseso ng pag-download sa ilang hakbang:
- Pagsisimula ng proseso - "POST /v2/{repoName}/blobs/uploads/"
- Pag-upload ng lifeline (gagamitin namin ang monolitikong pag-upload, ibig sabihin, ipapadala namin ang bawat lifeline sa kabuuan nito) - "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
Haba ng Nilalaman: {size of layer}
Uri ng Nilalaman: application/octet-stream
Layer Binary Data". - Nilo-load ang manifest - "PUT /v2/{repoName}/manifests/{reference}".
Ngunit ang dokumentasyon ay nakakaligtaan ng isang hakbang, kung wala ito ay walang gagana. Para sa monolithic loading, pati na rin para sa partial (chunked), bago i-load ang rail, dapat kang magsagawa ng PATCH request:
"PATCH /v2/{repoName}/blobs/uploads/{uuid}
Haba ng Nilalaman: {size of chunk}
Uri ng Nilalaman: application/octet-stream
{Layer Chunk Binary Data}".
Kung hindi, hindi ka makakagalaw sa unang punto, dahil... Sa halip na ang inaasahang sagot na code 202, makakatanggap ka ng 4xx.
Ngayon ang algorithm ay mukhang:
- Pagsisimula
- Patch rail
- Nilo-load ang handrail
- Nilo-load ang manifest
Ang mga puntos 2 at 3, ayon sa pagkakabanggit, ay uulitin nang maraming beses hangga't ang bilang ng mga linya ay kailangang i-load.
Una, kailangan namin ng anumang imahe. Gagamitin ko ang archlinux:latest
docker pull archlinux
Ngayon, i-save natin ito nang lokal para sa karagdagang pagsusuri
docker save c24fe13d37b9 -o savedArch
I-unpack ang resultang archive sa kasalukuyang direktoryo
tar xvf savedArch
Tulad ng nakikita mo, ang bawat lifeline ay nasa isang hiwalay na folder. Ngayon tingnan natin ang istraktura ng manifest na natanggap namin
cat manifest.json | json_pp
Hindi gaano. Tingnan natin kung anong manifest ang kailangan para i-load, ayon sa
Malinaw, hindi nababagay sa amin ang umiiral na manifesto, kaya gagawa kami ng sarili namin gamit ang blackjack at courtesans, lifelines at config.
Palagi kaming magkakaroon ng kahit isang config file at isang hanay ng mga lifeline. Bersyon 2 ng Scheme (kasalukuyan sa oras ng pagsulat), ang mediaType ay iiwang hindi magbabago:
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
Pagkatapos gawin ang pangunahing manifest, kailangan mong punan ito ng wastong data. Upang gawin ito, ginagamit namin ang json template ng rail object:
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": ${layersSizes[$i]},
"digest": "sha256:${layersNames[$i]}"
},
Idaragdag namin ito sa manifest para sa bawat riles.
Susunod, kailangan nating malaman ang laki ng config file at palitan ang mga stub sa manifest ng totoong data
sed -i "s/config_size/$configSize/g; s/config_hash/$configName/g" $manifestFile
Ngayon ay maaari mong simulan ang proseso ng pag-download at i-save ang iyong sarili ng uuid, na dapat na kasama ng lahat ng kasunod na kahilingan.
Ang kumpletong script ay mukhang ganito:
#!/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
maaari tayong gumamit ng isang handa na script:
./uploadImage.sh "~/path/to/saved/image" "http://localhost:8081/link/to/docker/registry" myRepoName 1.0
UPS:
Ano ang nakuha namin bilang isang resulta?
Una, ang totoong data para sa pagsusuri, dahil ang mga pagsubok ay pinapatakbo sa blazemeter at ang data sa mga kahilingan ng docker client ay hindi masyadong nagbibigay-kaalaman, hindi tulad ng mga purong HTTP na kahilingan.
Pangalawa, pinahintulutan kami ng paglipat na pataasin ang bilang ng mga virtual na user para sa pag-upload ng docker nang humigit-kumulang 150% at makakuha ng avg na oras ng pagtugon nang 20-25% na mas mabilis. Para sa pag-download ng docker, nagawa naming pataasin ang bilang ng mga user ng 500%, habang ang avg na oras ng pagtugon ay bumaba ng humigit-kumulang 60%.
Salamat sa iyo para sa iyong pansin.
Pinagmulan: www.habr.com