ΠΠΌΠ°Ρ ΠΌΠ΅ 2 ΡΠΎΡΠ±ΠΈ Ρ ΡΡΠ΅Π²Π°, 75 ΡΠ°Π±Π»Π΅ΡΠΊΠΈ ΠΌΠ΅ΡΠΊΠ°Π»ΠΈΠ½ unix ΡΡΠ΅Π΄Π°, Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ Π·Π° Π΄ΠΎΠΊΠ΅ΡΠΈ ΠΈ Π·Π°Π΄Π°ΡΠ°ΡΠ° Π΄Π° Π²Π½Π΅Π΄ΡΠΈΠΌ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈΡΠ΅ Π·Π° ΠΈΠ·ΡΠ΅Π³Π»ΡΠ½Π΅ ΠΈ ΠΈΠ·ΡΠ΅Π³Π»ΡΠ½Π΅ Π½Π° Π΄ΠΎΠΊΠ΅Ρ Π±Π΅Π· Π΄ΠΎΠΊΠ΅Ρ ΠΊΠ»ΠΈΠ΅Π½Ρ.
UPS:
ΠΡΠΏΡΠΎΡ: ΠΠ° ΠΊΠ°ΠΊΠ²ΠΎ Π΅ Π²ΡΠΈΡΠΊΠΎ ΡΠΎΠ²Π°?
ΠΡΠ³ΠΎΠ²ΠΎΡ: ΠΠ°ΡΠ΅Π΄Π΅ΡΠ΅ ΡΠ΅ΡΡΠ²Π°Π½Π΅ Π½Π° ΠΏΡΠΎΠ΄ΡΠΊΡΠ° (ΠΠ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ bash, ΡΠΊΡΠΈΠΏΡΠΎΠ²Π΅ΡΠ΅ ΡΠ° ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π΅Π½ΠΈ Π·Π° ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΠ΅Π»Π½ΠΈ ΡΠ΅Π»ΠΈ). ΠΠ΅ΡΠ΅ ΡΠ΅ΡΠ΅Π½ΠΎ Π΄Π° Π½Π΅ ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π΄ΠΎΠΊΠ΅Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΡΡ Π·Π° Π½Π°ΠΌΠ°Π»ΡΠ²Π°Π½Π΅ Π½Π° Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½ΠΈΡΠ΅ ΡΠ»ΠΎΠ΅Π²Π΅ (Π² ΡΠ°Π·ΡΠΌΠ½ΠΈ Π³ΡΠ°Π½ΠΈΡΠΈ) ΠΈ ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΎ Π΄Π° ΡΠ΅ Π΅ΠΌΡΠ»ΠΈΡΠ° ΠΏΠΎ-Π²ΠΈΡΠΎΠΊΠΎ Π½Π°ΡΠΎΠ²Π°ΡΠ²Π°Π½Π΅. Π ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Π½Π° ΡΠΎΠ²Π° Π²ΡΠΈΡΠΊΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΈ Π·Π°Π±Π°Π²ΡΠ½ΠΈΡ Π½Π° ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Π½Π° Docker Π±ΡΡ
Π° ΠΏΡΠ΅ΠΌΠ°Ρ
Π½Π°ΡΠΈ. ΠΠΎΠ»ΡΡΠΈΡ
ΠΌΠ΅ ΡΡΠ°Π²Π½ΠΈΡΠ΅Π»Π½ΠΎ ΡΠΈΡΡ ΡΠΎΠ²Π°Ρ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ Π²ΡΡΡ
Ρ ΠΏΡΠΎΠ΄ΡΠΊΡΠ°.
Π‘ΡΠ°ΡΠΈΡΡΠ° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° GNU Π²Π΅ΡΡΠΈΠΈ Π½Π° ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΈ.
ΠΡΡΠ²ΠΎ, Π½Π΅ΠΊΠ° ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌ ΠΊΠ°ΠΊΠ²ΠΎ ΠΏΡΠ°Π²ΡΡ ΡΠ΅Π·ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ.
Π ΡΠ°ΠΊΠ°, Π·Π° ΠΊΠ°ΠΊΠ²ΠΎ ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° docker pull? Π‘ΠΏΠΎΡΠ΅Π΄
βΠΠ·ΡΠ΅Π³Π»Π΅ΡΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ ΠΎΡ ΡΠ΅Π³ΠΈΡΡΡΡβ.
Π’Π°ΠΌ Π½Π°ΠΌΠΈΡΠ°ΠΌΠ΅ ΠΈ Π²ΡΡΠ·ΠΊΠ° ΠΊΡΠΌ
ΠΡ ΡΡΠΊ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌ, ΡΠ΅ Π΄ΠΎΠΊΠ΅Ρ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π΅ Π½Π°Π±ΠΎΡ ΠΎΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈ ΡΠ»ΠΎΠ΅Π²Π΅, ΠΊΠΎΠΈΡΠΎ ΡΡΠ΄ΡΡΠΆΠ°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ Π² ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ, ΠΊΠΎΠ΅ΡΠΎ ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎ Π΅ ΡΠΎΠ²Π°, ΠΎΡ ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ Π½ΡΠΆΠ΄Π°Π΅ΠΌ. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΡΠ°Π·Π³Π»Π΅ΠΆΠ΄Π°ΠΌΠ΅
Π’Π°ΠΌ ΡΠ΅ ΠΊΠ°Π·Π²Π° ΡΠ»Π΅Π΄Π½ΠΎΡΠΎ:
βΠΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΡ ΠΎΡ 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"
Π ΠΎΡΠ³ΠΎΠ²ΠΎΡ ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ 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
ΠΠ° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊΡΠ² ΡΠ°ΠΉΠ» ΠΏΠΎΠ»ΡΡΠΈΡ ΠΌΠ΅ Π½Π°ΠΉ-Π½Π°ΠΊΡΠ°Ρ ΠΊΠ°ΡΠΎ ΠΏΡΡΠ²Π° ΡΠΏΠ°ΡΠΈΡΠ΅Π»Π½Π° Π»ΠΈΠ½ΠΈΡ.
file firstLayer
ΡΠ΅Π·ΠΈ. lifelines ΡΠ° tar Π°ΡΡ ΠΈΠ²ΠΈ, ΠΊΠ°ΡΠΎ Π³ΠΈ ΡΠ°Π·ΠΎΠΏΠ°ΠΊΠΎΠ²Π°ΠΌΠ΅ Π² ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΈΡ ΡΠ΅Π΄ ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΠΌ ΡΡΠ΄ΡΡΠΆΠ°Π½ΠΈΠ΅ΡΠΎ Π½Π° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ.
ΠΠ΅ΠΊΠ° Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΠΌΠ°Π»ΡΠΊ bash ΡΠΊΡΠΈΠΏΡ, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ Π²ΡΠΈΡΠΊΠΎ ΡΠΎΠ²Π° Π΄Π° Π±ΡΠ΄Π΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠ°Π½ΠΎ
#!/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}
ΠΡΠ»ΠΆΠΈΠ½Π° Π½Π° ΡΡΠ΄ΡΡΠΆΠ°Π½ΠΈΠ΅ΡΠΎ: {ΡΠ°Π·ΠΌΠ΅Ρ Π½Π° ΡΠ»ΠΎΡ}
Content-Type: ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅/ΠΎΠΊΡΠ΅Ρ-ΠΏΠΎΡΠΎΠΊ
Π‘Π»ΠΎΠΉ Π΄Π²ΠΎΠΈΡΠ½ΠΈ Π΄Π°Π½Π½ΠΈ". - ΠΠ°ΡΠ΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΌΠ°Π½ΠΈΡΠ΅ΡΡΠ° - "PUT /v2/{repoName}/manifests/{reference}".
ΠΠΎ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡΠ° ΠΏΡΠΎΠΏΡΡΠΊΠ° Π΅Π΄Π½Π° ΡΡΡΠΏΠΊΠ°, Π±Π΅Π· ΠΊΠΎΡΡΠΎ Π½ΠΈΡΠΎ Π½ΡΠΌΠ° Π΄Π° ΡΠ°Π±ΠΎΡΠΈ. ΠΠ° ΠΌΠΎΠ½ΠΎΠ»ΠΈΡΠ½ΠΎ Π½Π°ΡΠΎΠ²Π°ΡΠ²Π°Π½Π΅, ΠΊΠ°ΠΊΡΠΎ ΠΈ Π·Π° ΡΠ°ΡΡΠΈΡΠ½ΠΎ (Π½Π° ΠΏΠ°ΡΡΠ΅ΡΠ°), ΠΏΡΠ΅Π΄ΠΈ Π΄Π° Π·Π°ΡΠ΅Π΄ΠΈΡΠ΅ ΡΠ΅Π»ΡΠ°ΡΠ°, ΡΡΡΠ±Π²Π° Π΄Π° ΠΈΠ·ΠΏΡΠ»Π½ΠΈΡΠ΅ PATCH Π·Π°ΡΠ²ΠΊΠ°:
"ΠΠΠ ΠΠΠ¦ΠΠ― /v2/{repoName}/blobs/uploads/{uuid}
ΠΡΠ»ΠΆΠΈΠ½Π° Π½Π° ΡΡΠ΄ΡΡΠΆΠ°Π½ΠΈΠ΅ΡΠΎ: {size of chunk}
Content-Type: ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅/ΠΎΠΊΡΠ΅Ρ-ΠΏΠΎΡΠΎΠΊ
{Layer Chunk Binary Data}".
Π ΠΏΡΠΎΡΠΈΠ²Π΅Π½ ΡΠ»ΡΡΠ°ΠΉ Π½ΡΠΌΠ° Π΄Π° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΡΠ΅ΠΌΠΈΠ½Π΅ΡΠ΅ ΠΎΡΠ²ΡΠ΄ ΠΏΡΡΠ²Π°ΡΠ° ΡΠΎΡΠΊΠ°, Π·Π°ΡΠΎΡΠΎ... ΠΠΌΠ΅ΡΡΠΎ ΠΎΡΠ°ΠΊΠ²Π°Π½ΠΈΡ ΠΊΠΎΠ΄ Π·Π° ΠΎΡΠ³ΠΎΠ²ΠΎΡ 202, ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ 4xx.
Π‘Π΅Π³Π° Π°Π»Π³ΠΎΡΠΈΡΡΠΌΡΡ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΡΠ°ΠΊΠ°:
- ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ
- Π Π΅Π»ΡΠ° Π·Π° ΠΊΡΡΠΏΠΊΠ°
- ΠΠ°ΡΠ΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΠ°ΡΠ°ΠΏΠ΅ΡΠ°
- ΠΠ°ΡΠ΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΌΠ°Π½ΠΈΡΠ΅ΡΡΠ°
Π’ΠΎΡΠΊΠΈ 2 ΠΈ 3, ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΎ, ΡΠ΅ Π±ΡΠ΄Π°Ρ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈ ΡΠΎΠ»ΠΊΠΎΠ²Π° ΠΏΡΡΠΈ, ΠΊΠΎΠ»ΠΊΠΎΡΠΎ Π±ΡΠΎΡ ΡΠ΅Π΄ΠΎΠ²Π΅ ΡΡΡΠ±Π²Π° Π΄Π° Π±ΡΠ΄Π°Ρ Π·Π°ΡΠ΅Π΄Π΅Π½ΠΈ.
ΠΡΡΠ²ΠΎ, ΠΈΠΌΠ°ΠΌΠ΅ Π½ΡΠΆΠ΄Π° ΠΎΡ Π²ΡΡΠΊΠΎ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ archlinux:latest
docker pull archlinux
Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° Π³ΠΎ Π·Π°ΠΏΠ°Π·ΠΈΠΌ Π»ΠΎΠΊΠ°Π»Π½ΠΎ Π·Π° Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π΅Π½ Π°Π½Π°Π»ΠΈΠ·
docker save c24fe13d37b9 -o savedArch
Π Π°Π·ΠΎΠΏΠ°ΠΊΠΎΠ²Π°ΠΉΡΠ΅ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π°ΡΡ ΠΈΠ² Π² ΡΠ΅ΠΊΡΡΠ°ΡΠ° Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ
tar xvf savedArch
ΠΠ°ΠΊΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅, Π²ΡΡΠΊΠ° ΡΠΏΠ°ΡΠΈΡΠ΅Π»Π½Π° Π»ΠΈΠ½ΠΈΡ Π΅ Π² ΠΎΡΠ΄Π΅Π»Π½Π° ΠΏΠ°ΠΏΠΊΠ°. Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° Π΄Π° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° Π½Π° ΠΌΠ°Π½ΠΈΡΠ΅ΡΡΠ°, ΠΊΠΎΠΉΡΠΎ ΠΏΠΎΠ»ΡΡΠΈΡ ΠΌΠ΅
cat manifest.json | json_pp
ΠΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ. ΠΠ΅ΠΊΠ° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊΡΠ² ΠΌΠ°Π½ΠΈΡΠ΅ΡΡ Π΅ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌ Π·Π° Π·Π°ΡΠ΅ΠΆΠ΄Π°Π½Π΅, ΡΠΏΠΎΡΠ΅Π΄
ΠΡΠ΅Π²ΠΈΠ΄Π½ΠΎ ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°ΡΠΈΡΡ ΠΌΠ°Π½ΠΈΡΠ΅ΡΡ Π½Π΅ Π½ΠΈ ΠΏΠΎΠ΄Ρ ΠΎΠΆΠ΄Π°, ΡΠ°ΠΊΠ° ΡΠ΅ ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈΠΌ Π½Π°Ρ ΡΠΎΠ±ΡΡΠ²Π΅Π½ Ρ Π±Π»Π΅ΠΊΠ΄ΠΆΠ΅ΠΊ ΠΈ ΠΊΡΡΡΠΈΠ·Π°Π½ΠΊΠΈ, ΡΠΏΠ°ΡΠΈΡΠ΅Π»Π½ΠΈ Π»ΠΈΠ½ΠΈΠΈ ΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ.
ΠΠΈΠ½Π°Π³ΠΈ ΡΠ΅ ΠΈΠΌΠ°ΠΌΠ΅ ΠΏΠΎΠ½Π΅ Π΅Π΄ΠΈΠ½ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΎΠ½Π΅Π½ ΡΠ°ΠΉΠ» ΠΈ ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΠΏΠ°ΡΠΈΡΠ΅Π»Π½ΠΈ Π»ΠΈΠ½ΠΈΠΈ. Π‘Ρ Π΅ΠΌΠ° Π²Π΅ΡΡΠΈΡ 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
UPS:
ΠΠ°ΠΊΠ²ΠΎ ΠΏΠΎΠ»ΡΡΠΈΡ
ΠΌΠ΅ Π² ΡΠ΅Π·ΡΠ»ΡΠ°Ρ?
ΠΡΡΠ²ΠΎ, ΡΠ΅Π°Π»Π½ΠΈ Π΄Π°Π½Π½ΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·, ΡΡΠΉ ΠΊΠ°ΡΠΎ ΡΠ΅ΡΡΠΎΠ²Π΅ΡΠ΅ ΡΠ΅ ΠΈΠ·ΠΏΡΠ»Π½ΡΠ²Π°Ρ Π² blazemeter ΠΈ Π΄Π°Π½Π½ΠΈΡΠ΅ Π·Π° ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈΡΠ΅ Π·Π°ΡΠ²ΠΊΠΈ Π½Π° Π΄ΠΎΠΊΠ΅Ρ Π½Π΅ ΡΠ° ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠ²Π½ΠΈ, Π·Π° ΡΠ°Π·Π»ΠΈΠΊΠ° ΠΎΡ ΡΠΈΡΡΠΈΡΠ΅ HTTP Π·Π°ΡΠ²ΠΊΠΈ.
ΠΡΠΎΡΠΎ, ΠΏΡΠ΅Ρ ΠΎΠ΄ΡΡ Π½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π΄Π° ΡΠ²Π΅Π»ΠΈΡΠΈΠΌ Π±ΡΠΎΡ Π½Π° Π²ΠΈΡΡΡΠ°Π»Π½ΠΈΡΠ΅ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈ Π·Π° ΠΊΠ°ΡΠ²Π°Π½Π΅ Π½Π° Π΄ΠΎΠΊΠ΅ΡΠΈ Ρ ΠΎΠΊΠΎΠ»ΠΎ 150% ΠΈ Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΠΌ ΡΡΠ΅Π΄Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅ Π·Π° ΡΠ΅Π°ΠΊΡΠΈΡ Ρ 20-25% ΠΏΠΎ-Π±ΡΡΠ·ΠΎ. ΠΠ° ΠΈΠ·ΡΠ΅Π³Π»ΡΠ½Π΅ Π½Π° docker ΡΡΠΏΡΡ ΠΌΠ΅ Π΄Π° ΡΠ²Π΅Π»ΠΈΡΠΈΠΌ Π±ΡΠΎΡ Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ Ρ 500%, Π΄ΠΎΠΊΠ°ΡΠΎ ΡΡΠ΅Π΄Π½ΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ Π·Π° ΡΠ΅Π°ΠΊΡΠΈΡ Π½Π°ΠΌΠ°Π»Ρ Ρ ΠΎΠΊΠΎΠ»ΠΎ 60%.
ΠΠ»Π°Π³ΠΎΠ΄Π°ΡΡ Π²ΠΈ Π·Π° Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ΡΠΎ.
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com