HTTP рдЕрдиреБрд░реЛрдз рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ docker рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдмрд┐рдирд╛ docker рдЦреАрдВрдЪрдиреЗ рдФрд░ docker рдкреБрд╢ рдХрдорд╛рдВрдб рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди

рд╣рдо рдШрд╛рд╕ рдХреЗ 2 рдмреИрдЧ, рдореЗрд╕рдХрд▓рд╛рдЗрди рдХреА 75 рдЧреЛрд▓рд┐рдпрд╛рдВ рдпреВрдирд┐рдХреНрд╕ рдкрд░реНрдпрд╛рд╡рд░рдг, рдбреЙрдХрд░реНрд╕ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдФрд░ рдбреЙрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдмрд┐рдирд╛ рдбреЙрдХ рдкреБрд▓ рдФрд░ рдбреЙрдХ рдкреБрд╢ рдХрдорд╛рдВрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдпред



UPD:
рдкреНрд░рд╢реНрди: рдпрд╣ рд╕рдм рдХрд┐рд╕ рд▓рд┐рдП рд╣реИ?
рдЙрддреНрддрд░: рдЙрддреНрдкрд╛рдж рдХрд╛ рд▓реЛрдб рдкрд░реАрдХреНрд╖рдг (рдмрд╢ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирд╣реАрдВ, рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╢реИрдХреНрд╖рд┐рдХ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рддреА рд╣реИрдВ)ред рдпрд╣ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░рддреЗрдВ (рдЙрдЪрд┐рдд рд╕реАрдорд╛ рдХреЗ рднреАрддрд░) рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЙрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ рдФрд░, рддрджрдиреБрд╕рд╛рд░, рдПрдХ рдЙрдЪреНрдЪ рднрд╛рд░ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░реЗрдВред рдирддреАрдЬрддрди, docker рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд╕рднреА рд╕рд┐рд╕реНрдЯрдо рджреЗрд░реА рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╕реАрдзреЗ рдЙрддреНрдкрд╛рдж рдкрд░ рдПрдХ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╕рд╛рдл рд▓реЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛


рдкрд╣рд▓реЗ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпреЗ рдЯреАрдореЗрдВ рдХреНрдпрд╛ рдХрд░рддреА рд╣реИрдВред


рддреЛ рдХреНрдпрд╛ рдбреЙрдХрдЯрд░ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ? рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдЕрдиреБрд╕рд╛рд░ :


"рдПрдХ рдЫрд╡рд┐ рдпрд╛ рдПрдХ рд░рдЬрд┐рд╕реНрдЯреНрд░реА рд╕реЗ рдПрдХ рднрдВрдбрд╛рд░ рдЦреАрдВрдЪреЛ"ред

рд╡рд╣рд╛рдБ рд╣рдо рдЫрд╡рд┐рдпреЛрдВ, рдХрдВрдЯреЗрдирд░реЛрдВ рдФрд░ рднрдВрдбрд╛рд░рдг рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рдкрд╛рддреЗ рд╣реИрдВ ред



docker image layers, , . registry API.


:


"An тАЬimageтАЭ is a combination of a JSON manifest and individual layer files. The process of pulling an > image centers around retrieving these two components."

тАЬPulling an Image ManifestтАЭ.


, . : GET /v2/{name}/manifests/{reference}


"The name and reference parameter identify the image and are required. The reference may include a tag or digest."

, :


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}"


тАЬAccess to a layer will be gated by the name of the repository but is identified uniquely in the registry by digest.тАЭ

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


.. tar , .



#!/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 тАФ docker push


.


. , . .


:


  • тАФ "POST /v2/{repoName}/blobs/uploads/"
  • ( , .. ) тАФ "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
    Content-Length: {size of layer}
    Content-Type: application/octet-stream
    Layer Binary Data".
  • тАФ "PUT /v2/{repoName}/manifests/{reference}".

, . (chunked) PATCH :


"PATCH /v2/{repoName}/blobs/uploads/{uuid}
Content-Length: {size of chunk}
Content-Type: application/octet-stream
{Layer Chunk Binary Data}".


, .. 202 4.


:



  • 2 3 , .

. archlinux:latest


docker pull archlinux



docker save c24fe13d37b9 -o savedArch



tar xvf savedArch


. ,


cat manifest.json | json_pp


. , .



, .


config . 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 "\n\t]\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

рдЖрд▓реЗрдЦ рдиреЗ GNU рд╕рдВрд╕реНрдХрд░рдг рдЯреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред


рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд▓реЗрдЦ рдЕрдореЗрд░рд┐рдХрд╛ рдХреА рдЦреЛрдЬ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдбреЗрдЯрд╛ рдХреЛ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдЕрдВрддрд░рд╛рд▓ рдХреЛ рдкреВрд░рдХ рдХрд░рддрд╛ рд╣реИред рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред


All Articles