РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

Π£ нас Π±Ρ‹Π»ΠΎ 2 мСшка Ρ‚Ρ€Π°Π²Ρ‹, 75 Ρ‚Π°Π±Π»Π΅Ρ‚ΠΎΠΊ мСскалина unix environment, docker Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ ΠΈ Π·Π°Π΄Π°Ρ‡Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ docker pull ΠΈ docker push Π±Π΅Π· Π΄ΠΎΠΊΠ΅Ρ€ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°.

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

UPD:
Вопрос: Для Ρ‡Π΅Π³ΠΎ всё это?
ΠžΡ‚Π²Π΅Ρ‚: НагрузочноС тСстированиС ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Π° (НЕ срСдствами баша, скрипты ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Ρ‹ Π² ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… цСлях). НС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄ΠΎΠΊΠ΅Ρ€ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±Ρ‹Π»ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΎ для ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΡ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… прослоСк (Π² Ρ€Π°Π·ΡƒΠΌΠ½Ρ‹Ρ… ΠΏΡ€Π΅Π΄Π΅Π»Π°Ρ…) ΠΈ соотвСтствСнно эмулирования Π±ΠΎΠ»Π΅Π΅ высокой Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ ΡƒΠ±Ρ€Π°Π»ΠΈ всС систСмныС Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΈ Π΄ΠΎΠΊΠ΅Ρ€ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°. ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ ΡΡ€Π°Π²Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‡ΠΈΡΡ‚ΡƒΡŽ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ нСпосрСдствСнно Π½Π° ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚.
Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ использовались Ρ‚ΡƒΠ»Ρ‹ GNU вСрсий.

Для Π½Π°Ρ‡Π°Π»Π° разбСрСмся Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°ΡŽΡ‚ эти ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹.

Π˜Ρ‚Π°ΠΊ для Ρ‡Π΅Π³ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ docker pull? Богласно Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ:

"Pull an image or a repository from a registry".

Π’Π°ΠΌ ΠΆΠ΅ Π½Π°Ρ…ΠΎΠ΄ΠΈΠΌ ссылку Π½Π° understand images, containers, and storage drivers.

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

ΠžΡ‚ΡΡŽΠ΄Π° ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ½ΡΡ‚ΡŒ Ρ‡Ρ‚ΠΎ 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"

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

Π’ ΠΎΡ‚Π²Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ 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

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

посмотрим Ρ‡Ρ‚ΠΎ Π·Π° Ρ„Π°ΠΉΠ» ΠΌΡ‹ Π² ΠΈΡ‚ΠΎΠ³Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Π² качСствС ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Π»Π΅Π΅Ρ€Π°.

file firstLayer

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

Ρ‚.Π΅. Π»Π΅Π΅Ρ€Ρ‹ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΈΠ· сСбя 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 pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

Π’Π΅ΠΏΠ΅Ρ€ΡŒ сохраним Π΅Π³ΠΎ сСбС локально для дальнСйшСго Ρ€Π°Π·Π±ΠΎΡ€Π°

docker save c24fe13d37b9 -o savedArch

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

РаспакуСм ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΉ Π°Ρ€Ρ…ΠΈΠ² Π² Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ

tar xvf savedArch

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

Как Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π»Π΅Π΅Ρ€ Π»Π΅ΠΆΠΈΡ‚ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΠ°ΠΏΠΊΠ΅. Π’Π΅ΠΏΠ΅Ρ€ΡŒ посмотрим Π½Π° струткуру манифСста, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ

cat manifest.json | json_pp

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

НС густо. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ ΠΊΠ°ΠΊΠΎΠΉ манифСст Π½ΡƒΠΆΠ΅Π½ для Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ, согласно Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.

РСализация ΠΊΠΎΠΌΠ°Π½Π΄ docker pull ΠΈ docker push Π±Π΅Π· docker ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° посрСдством HTTP запросов

ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ манифСст Π½Π°ΠΌ Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚, Π·Π½Π°Ρ‡ΠΈΡ‚ сдСлаСм свой с блэкдТСком ΠΈ ΠΊΡƒΡ€Ρ‚ΠΈΠ·Π°Π½ΠΊΠ°ΠΌΠΈ Π»Π΅Π΅Ρ€Π°ΠΌΠΈ ΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°ΠΌΠΈ.

Π£ нас всСгда Π±ΡƒΠ΄Π΅Ρ‚ ΠΌΠΈΠ½ΠΌΡƒΠΌ ΠΎΠ΄ΠΈΠ½ 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

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ процСсс Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΈ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ сСбС 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

UPD:
Π§Ρ‚ΠΎ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅?
Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ для Π°Π½Π°Π»ΠΈΠ·Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΠΎΡƒ тСсты Π·Π°ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ΡΡ Π² blazemeter ΠΈ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ запросам Π΄ΠΎΠΊΠ΅Ρ€ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° вСсьма Π½Π΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΠ²Π½Ρ‹Π΅ Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠΈ ΠΎΡ‚ чистых HTTP запросов.

Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ» Π½Π°ΠΌ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ колличСство Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ для docker upload ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Π½Π° 150% ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€ΠΈ этом avg response time Π½Π° 20-25% быстрСС. Для docker download ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ количСство ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Π½Π° 500%, avg response time ΠΏΡ€ΠΈ этом снизился ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Π½Π° 60%.

Бпасибо за вниманиС.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ