Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

2 belar poltsa, 75 mescaline tablet unix ingurunea, docker biltegi bat eta docker pull eta docker push komandoak docker bezerorik gabe ezartzeko zeregina genituen.

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

UPS:
Galdera: Zertarako da hau guztia?
Erantzuna: kargatu produktuaren probak (EZ da bash erabiltzen, script-ak hezkuntza-helburuetarako ematen dira). Docker bezeroa ez erabiltzea erabaki zen geruza gehigarriak murrizteko (arrazoizko mugaren barruan) eta, horren arabera, karga handiagoa emulatzeko. Ondorioz, Docker bezeroaren sistemaren atzerapen guztiak kendu ziren. Karga nahiko garbia jaso genuen zuzenean produktuan.
Artikuluak tresnen GNU bertsioak erabiltzen zituen.

Lehenik eta behin, ikus dezagun komando hauek zer egiten duten.

Beraz, zertarako erabiltzen da docker pull? Ren arabera dokumentazioa:

"Atera irudi bat edo biltegi bat erregistro batetik".

Bertan esteka bat ere aurkituko dugu irudiak, edukiontziak eta biltegiratze kontrolatzaileak ulertzea.

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Hemendik aurrera uler dezakegu docker irudi bat irudiaren azken aldaketei buruzko informazioa duten geruza jakin batzuen multzoa dela, eta hori da, jakina, behar duguna. Jarraian begiratuko dugu erregistroko APIa.

Honako hau dio:

""Irudi bat" JSON manifestu baten eta geruza indibidualaren fitxategien konbinazioa da. Irudi bat ateratzeko prozesua bi osagai hauek berreskuratzean oinarritzen da."

Beraz, dokumentazioaren arabera lehen urratsa da "Irudi manifestua ateratzea".

Noski, ez dugu filmatuko, baina bertako datuak behar ditugu. Honakoa da eskaera adibide bat: GET /v2/{name}/manifests/{reference}

"Izenak eta erreferentzia-parametroak irudia identifikatzen dute eta beharrezkoak dira. Erreferentziak etiketa edo laburpena izan dezake".

Gure docker biltegia lokalean zabaltzen da, saia gaitezen eskaera exekutatzen:

curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/manifests/1.1.1" -H "header_if_needed"

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Erantzun gisa, json jasotzen dugu gaur egun bizi-lerroak soilik interesatzen zaizkigunak, edo hobeto esanda, haien hashak. Jasotakoan, bakoitzaren bidez pasa eta eskaera hau exekutatu dezakegu: "GET /v2/{izena}/blobs/{digest}"

"Geruza baterako sarbidea biltegiaren izenaren arabera itxiko da, baina laburpenaren bidez erregistroan identifikatzen da".

digest kasu honetan jaso dugun hash-a da.

Saiatzen

curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/blobs/sha256:f972d139738dfcd1519fd2461815651336ee25a8b54c358834c50af094bb262f" -H "header_if_needed" --output firstLayer

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Ea zer nolako fitxategia jaso genuen azkenean lehen salbamendu gisa.

file firstLayer

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

horiek. errailak tar artxiboak dira, dagokion ordenan desegitean irudiaren edukia lortuko dugu.

Idatz dezagun bash script txiki bat, hau guztia automatizatu ahal izateko

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

Orain nahi diren parametroekin exekutatu eta beharrezko irudiaren edukia lor dezakegu

./script.sh dirName β€œhttp://localhost:8081/link/to/docker/registry” myAwesomeImage 1.0

2. zatia - Docker push

Hau pixka bat konplexuagoa izango da.

Has gaitezen berriro dokumentazioa. Beraz, lider bakoitza deskargatu behar dugu, dagokion manifestua bildu eta hura ere deskargatu. Sinplea dirudi.

Dokumentazioa aztertu ondoren, deskarga prozesua hainbat urratsetan banatu dezakegu:

  • Prozesuaren hasieratzea - ​​"POST /v2/{repoName}/blobs/uploads/"
  • Bizi-lerro bat kargatzea (karga monolitiko bat erabiliko dugu, hau da, bizi-lerro bakoitza bere osotasunean bidaltzen dugu) - "JARRI /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
    Eduki-luzera: {geruzaren tamaina}
    Eduki-mota: aplikazioa/octet-stream
    Geruzako datu bitarrak".
  • Manifestua kargatzen - "PUT /v2/{repoName}/manifests/{reference}".

Baina dokumentazioak urrats bat galtzen du, eta hori gabe ezer ez da funtzionatuko. Karga monolitikoan, baita partzialean ere (zatian), erraila kargatu aurretik, PATCH eskaera egin behar duzu:

"PATXEA /v2/{repoName}/blobs/uploads/{uuid}
Eduki-luzera: {zatiaren tamaina}
Eduki-mota: aplikazioa/octet-stream
{Layer Chunk Binary Data}".

Bestela, ezin izango zara lehen puntutik haratago joan, zeren... Espero den erantzun-kodearen 202 ordez, 4xx jasoko duzu.

Orain algoritmoak itxura hau du:

  • Hasieraketa
  • Adabaki erraila
  • Baranda kargatzea
  • Manifestua kargatzen
    2. eta 3. puntuak, hurrenez hurren, lerro kopurua kargatu behar den adina aldiz errepikatuko dira.

Lehenik eta behin, edozein irudi behar dugu. Archlinux:latest erabiliko dut

docker pull archlinux

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Orain gorde dezagun lokalean azterketa gehiago egiteko

docker save c24fe13d37b9 -o savedArch

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Sortutako artxiboa deskonprimitu uneko direktorioan

tar xvf savedArch

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Ikus dezakezunez, bizi-lerro bakoitza karpeta bereizi batean dago. Ikus dezagun orain jaso dugun manifestuaren egitura

cat manifest.json | json_pp

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Ez asko. Ikus dezagun zer manifestua behar den kargatzeko, arabera dokumentazioa.

Docker pull eta docker push komandoak ezartzea docker bezerorik gabe HTTP eskaerak erabiliz

Bistan denez, dagoen manifestua ez zaigu egokitzen, beraz, gurea egingo dugu blackjack eta kortesanekin, salbamenduekin eta konfigurazioekin.

Beti izango dugu gutxienez konfigurazio fitxategi bat eta bizi-lerro sorta bat. 2. eskemaren bertsioa (unea idazteko unean), mediaType aldatu gabe geratuko da:

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

Oinarrizko manifestua sortu ondoren, baliozko datuekin bete behar duzu. Horretarako, errail-objektuaren json txantiloia erabiltzen dugu:

{
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": ${layersSizes[$i]},
         "digest": "sha256:${layersNames[$i]}"
      },

Errail bakoitzeko manifestuari gehituko diogu.

Ondoren, konfigurazio-fitxategiaren tamaina ezagutu eta manifestuko zirriborroak datu errealekin ordezkatu behar ditugu

sed -i "s/config_size/$configSize/g; s/config_hash/$configName/g" $manifestFile

Orain deskarga prozesua abiarazi eta uuid bat gorde dezakezu, ondorengo eskaera guztiekin batera joan beharko litzatekeena.

Gidoi osoa honelako itxura du:

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

prest egindako script bat erabil dezakegu:

./uploadImage.sh "~/path/to/saved/image" "http://localhost:8081/link/to/docker/registry" myRepoName 1.0

UPS:
Zer lortu dugu horren ondorioz?
Lehenik eta behin, analisirako datu errealak, probak blazemeter-en egiten baitira eta docker bezeroen eskaeren datuak ez dira oso informatiboak, HTTP eskaera hutsak ez bezala.

Bigarrenik, trantsizioak docker kargatzeko erabiltzaile birtualen kopurua % 150 inguru handitzeko eta batez besteko erantzun-denbora % 20-25 azkarrago lortzeko aukera eman zigun. Docker deskargatzeko, erabiltzaileen kopurua % 500 handitzea lortu dugu, eta batez besteko erantzun-denbora % 60 inguru murriztu zen bitartean.

Eskerrik asko zure arretagatik.

Iturria: www.habr.com

Gehitu iruzkin berria