Nós tínhamos 2 sacos de grama, 75 comprimidos de mescalina ambiente unix, repositório do docker e tarefa para implementar comandos pull e pull do docker sem o cliente do docker.

UPD:
Pergunta: Para que serve tudo isso?
Resposta: Teste de carga do produto (NÃO por meio do bash, os scripts são fornecidos para fins educacionais). Foi decidido não usar o cliente do docker para reduzir camadas adicionais (dentro de limites razoáveis) e, consequentemente, emular uma carga mais alta. Como resultado, todos os atrasos do sistema do cliente docker foram removidos. Recebeu uma carga relativamente limpa diretamente no produto
Primeiro, vamos ver o que essas equipes fazem.
Então, para que é utilizado o docker pull? De acordo com a documentação :
"Puxe uma imagem ou um repositório de um registro".
Lá, encontramos um link para entender imagens, contêineres e drivers de armazenamento .

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 , .
downloadDir=$1
url=$2
imageName=$3
tag=$4
layers=($(curl -s -X GET "$url/v2/$imageName/manifests/$tag" | grep -oP '(?<=blobSum" : ").+(?=")'))
for layer in "${layers[@]}"; do
echo "Downloading ${layer}"
curl -v -X GET "$url/v2/$imageName/blobs/$layer" --output "$downloadDir/$layer.tar"
done
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.
:
. 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
Agora você pode iniciar o processo de inicialização e salvar o uuid, que deve ser acompanhado por todas as solicitações subsequentes.
O script completo é mais ou menos assim:
imageDir=$1
url=$2
repoName=$3
tag=$4
manifestFile=$(readlink -f ${imageDir}/manifestCopy)
configFile=$(readlink -f $(find $imageDir -name "*.json" ! -name "manifest.json"))
function prepareLayersForUpload() {
info_file=$imageDir/info
layersNames=($(find $imageDir -name "layer.tar" -exec shasum -a 256 {} \; | cut -d" " -f1))
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
truncate -s-2 $manifestFile
printf "\n\t]\n}" >> $manifestFile
}
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
}
prepareLayersForUpload
setConfigProps
cat $manifestFile
uuid=$(curl -s -X POST -I "$url/v2/$repoName/blobs/uploads/" | grep -oP "(?<=Docker-Upload-Uuid: ).+")
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"
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
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"
curl -v -X PUT "$url/v2/$repoName/manifests/$tag" \
-H 'Content-Type: application/vnd.docker.distribution.manifest.v2+json' \
--data-binary "@$manifestFile"
exit 0
podemos usar um script pronto:
./uploadImage.sh "~/path/to/saved/image" "http://localhost:8081/link/to/docker/registry" myRepoName 1.0
O artigo usou as ferramentas de versão GNU.
Em geral, o artigo não descobre os Estados Unidos, mas estrutura ligeiramente os dados díspares e suplementa as lacunas na documentação. Obrigado pela leitura.