HTTP درخواستوں کا استعمال کرتے ہوئے ڈوکر کلائنٹ کے بغیر ڈوکر پل اور ڈوکر پش کمانڈز کو نافذ کرنا

ہمارے پاس گھاس کے 2 تھیلے، 75 میسکلین گولیاں یونکس ماحول، ایک ڈوکر ریپوزٹری اور ڈوکر کلائنٹ کے بغیر ڈوکر پل اور ڈوکر پش کمانڈز کو نافذ کرنے کا کام تھا۔

HTTP درخواستوں کا استعمال کرتے ہوئے ڈوکر کلائنٹ کے بغیر ڈوکر پل اور ڈوکر پش کمانڈز کو نافذ کرنا

یوپیڈی:
سوال: یہ سب کس لیے ہے؟
جواب: پروڈکٹ کی لوڈ ٹیسٹنگ (بش کا استعمال نہیں، اسکرپٹ تعلیمی مقاصد کے لیے فراہم کیے گئے ہیں)۔ یہ فیصلہ کیا گیا کہ ڈوکر کلائنٹ کو اضافی تہوں کو کم کرنے کے لیے استعمال نہ کیا جائے (مناسب حد کے اندر) اور اس کے مطابق، زیادہ بوجھ کی تقلید کریں۔ نتیجے کے طور پر، Docker کلائنٹ کی تمام نظام کی تاخیر کو ہٹا دیا گیا تھا. ہمیں براہ راست پروڈکٹ پر نسبتاً صاف بوجھ ملا۔
مضمون میں ٹولز کے 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 درخواست کرنا ضروری ہے:

"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 (تحریر کے وقت موجودہ)، 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

اب آپ ڈاؤن لوڈ کا عمل شروع کر سکتے ہیں اور اپنے آپ کو ایک 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

نیا تبصرہ شامل کریں