áá»áœááºá¯ááºááá¯á·ááœáẠááŒááºá¡ááẠá á¡áááºá áááºá áá¬ááá¯ááºáž áááºáááẠáá áá¯á¶áž Unix áááºáááºážáá»ááºá docker ááá¯ááŸá±á¬ááºáááºážááŸáá·áº docker áááá¯ááºážááá·áºááá«áá² docker ááœá²áá°ááŒááºážááŸáá·áº docker push ááœáŸááºááŒá¬ážáá»ááºáá»á¬ážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááẠáá¬áááºááŸááááºá
UPD:
áá±áž- áá«ááœá±á¡á¬ážáá¯á¶ážá áá¬á¡ááœááºáá²á
á¡ááŒá±- áá¯ááºáá¯ááºáá
ááºážáááºááŸá¯ááᯠáááºáá« (bash ááá¯á¶ážáá«á scripts áá»á¬ážááᯠááá¬áá±ážááá¯ááºáá¬áááºááœááºáá»ááºáá»á¬ážá¡ááœáẠáá¶á·ááá¯ážáá±ážáááº)á áááºáá±á¬ááºážá¡ááœáŸá¬áá»á¬ážááᯠ(áá»áá¯ážááŒá±á¬ááºážáá®áá»á±á¬áºáá±á¬ááá·áºáááºáá»ááºáá»á¬ážá¡ááœááºáž) áá»áŸá±á¬á·áá»ááẠdocker client ááá¯á¡áá¯á¶ážáááŒá¯ááẠáá¯á¶ážááŒááºáá²á·ááŒá®ážá ááá¯á·ááŒá±á¬áá·áº ááá¯ááá¯ááŒáá·áºáá¬ážáá±á¬áááºááᯠá¡áá¯áá°ááẠáá¯á¶ážááŒááºáá²á·áááºá ááááºá¡áá±ááŒáá·áº Docker client á á
áá
áºááŸá±á¬áá·áºááŸá±ážááŸá¯á¡á¬ážáá¯á¶ážááᯠáááºááŸá¬ážáá²á·áááºá áá»áœááºá¯ááºááá¯á·ááẠáá¯ááºáá¯ááºá¡áá±á«áº ááá¯ááºááá¯áẠááá·áºááŸááºážáá±á¬áááºááᯠáááºáá¶áááŸááá²á·áá«áááºá
áá±á¬ááºážáá«ážááœáẠGNU áá¬ážááŸááºážáá»á¬ážááᯠá¡áá¯á¶ážááŒá¯áá¬ážáááºá
áŠážá áœá¬á á€á¡áááá·áºáá±á¬áºáá»á¬ážááẠá¡áááºá¡áá¬áá¯ááºáá±á¬ááºáááºááᯠá¡ááŒá±ááŸá¬ááŒáá·áºááŒáá«á áá¯á·á
áá«ááᯠDocker Pull ááᯠáá¬á¡ááœááºáá¯á¶ážáá¬áá²á á¡á
"ááŸááºáá¯á¶áááºáá áºáá¯á០áá¯á¶ ááá¯á·ááá¯áẠááá¯ááŸá±á¬ááºáááºážááᯠááœá²áá°áá«á"
á¡á²áá®ááŸá¬ ááá·áºááºáá
áºáá¯ááá¯áááºáž ááœá±á·áááºá
á€áá±áá¬ááŸáá±á docker áá¯á¶ááẠáá»áœááºá¯ááºááá¯á·ááá¯á¡ááºáá±á¬á¡áá¬ááŒá
áºáááºááŸá¬ áááá¬áááºááŸá¬ážáá±á¬ áá¯ááºáá¯á¶ááá±á¬ááºáá¯á¶ážááŒá±á¬ááºážáá²ááŸá¯áá»á¬ážááŸáá·áºáááºáááºááá·áº á¡áá»ááºá¡áááºáá»á¬ážáá«ááŸááá±á¬ á¡áá»áá¯á·áá±á¬á¡ááœáŸá¬áá»á¬ážááŒá
áºááŒá±á¬ááºáž áá»áœááºá¯ááºááá¯á·áá¬ážáááºááá¯ááºáá«áááºá áá±á¬ááºáá
áºáᯠáá»áœááºáá±á¬áºááá¯á· ááŒáá·áºáááºá
áááºážááẠá¡á±á¬ááºáá«á¡ááá¯ááºážááá¯áááºá
""áá¯á¶" ááẠJSON áááºáá®ážáááºá áºááŸáá·áº á¡ááœáŸá¬áá áºáá¯áá»ááºážá á®á á¡ááœáŸá¬ááá¯ááºáá»á¬áž áá±á«ááºážá ááºááŸá¯ááŒá áºáááºá á¡ááá¯áá« á¡á áááºá¡ááá¯ááºážááŸá áºáá¯ááᯠááŒááºáááºááá°áá¬ááœáẠ> áá¯á¶áá áºáá¯á¶ááᯠááœá²áá¯ááºááá·áº áá¯ááºáááºážá ááºááẠáááá¯áá»ááºááŒá áºáááºá"
áá«ááŒá±á¬áá·áº á á¬ááœááºá á¬áááºážááœá±á¡á áááá¡ááá·áºá "Image Manifest ááá¯ááœá²ááŒááºážá"á
áá¯ááºáá«áááºá áá«ááá¯á·á á¡á²áá«ááᯠáá
áºááŸá¬ááá¯ááºáá°ážá áá«áá±ááá·áº áá«ááá¯á·á áá±áá¬ááœá±ááá¯áááºá á¡á±á¬ááºááœááºáá±á¬áºááŒáá¬ážáá±á¬ áá±á¬ááºážááá¯áá»ááºááŸá¬ á¥ááá¬áá
áºáá¯ááŒá
áºáááºá GET /v2/{name}/manifests/{reference}
"á¡áááºááŸáá·áº áááºááœáŸááºážááŸá¯ ááá·áºáááºáá»ááºááẠáá¯á¶á¡á¬áž ááœá²ááŒá¬ážáááºááŸááºááŒá®áž ááá¯á¡ááºáá«áááºá ááá¯ážáá¬ážáá»ááºááœáẠááẠááá¯á·ááá¯áẠá¡áá»á±á¡ááẠáá«áááºááá¯ááºáááºá"
áá»áœááºá¯ááºááá¯á·á docker repository ááᯠá ááºááœááºážááœáẠá¡áá¯á¶ážááŒá¯áá¬ážááŒá®ážá áá±á¬ááºážááá¯áá»ááºááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááẠááŒáá¯ážá á¬ážááŒáá«á áá¯á·á
curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/manifests/1.1.1" -H "header_if_needed"
áá¯á¶á·ááŒááºááŸá¯á¡áá±ááŒáá·áºá áá»áœááºá¯ááºááá¯á·ááẠáááºááŸáá¡áááºááœá±ážááŒá±á¬áá»á¬áž ááá¯á·ááá¯áẠáááºážááá¯á·á hashe áá»á¬ážááá¯áᬠá áááºáááºá á¬ážááá·áº json ááᯠáááºáá¶áááŸááá«áááºá áááºážááá¯á·ááᯠáááºáá¶áááŸáááŒá®ážáá±á¬ááºá áá áºáá¯áá»ááºážá á®ááŸáá áºááá·áº áá»áœááºá¯ááºááá¯á·ááẠá¡á±á¬ááºáá«áá±á¬ááºážááá¯áá»ááºááᯠáá¯ááºáá±á¬ááºááá¯ááºáááº- "GET /v2/{name}/blobs/{digest}"
"á¡ááœáŸá¬áá áºáá¯ááá¯á·áááºáá±á¬ááºááŒááºážááᯠrepository áá¡áááºááŒáá·áºáá¶áá«ážááááºáááá·áºáááºááŒá áºáá±á¬áºáááºážá ááŸááºáá¯á¶áááºááŒááºážááœááºáá°ážááŒá¬ážá áœá¬ááœá²ááŒá¬ážáááºááŸááºáá¬ážáááºá"
á€ááá á¹á ááœáẠdigest áááºáá»áœááºá¯ááºááá¯á·áááŸááá¬ážáá±á¬ hash ááŒá áºáááºá
ááŒáá¯ážá á¬ážáá±áá«áááºá
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
á¡á²áá«ááœá±á ááá¬ážáááºážáá»á¬ážááẠááá¹ááá¬á á±áž áá±á¬áºááœááºážááá¯ááºáá»á¬ážááŒá áºááŒá®áž áááºážááá¯á·ááᯠááá·áºáá»á±á¬áºáá±á¬ á¡á á®á¡á á¥áºá¡ááá¯ááºáž áá¯ááºááá¯ážááŒá®áž áá¯á¶á á¡ááŒá±á¬ááºážá¡áá¬áá»á¬ážááᯠáá»áœááºá¯ááºááá¯á· áááŸááááºááŒá áºáááºá
áá«ááœá±á¡á¬ážáá¯á¶áž á¡ááá¯á¡áá»á±á¬ááºááŒá áºááá¯ááºá¡á±á¬áẠbash script áá±ážáá áºáá¯áá±ážááá¯ááºáá¡á±á¬ááº
#!/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/"
- á¡áááºááœá±ážááŒá±á¬áá
áºáá¯ááᯠá¡ááºáá¯ááºáááºááŒááºáž (áá»áœááºá¯ááºááá¯á·ááẠmonolithic á¡ááºáá¯ááºááᯠá¡áá¯á¶ážááŒá¯áá«áááºá ááá¯ááá¯áááºááŸá¬ áá»áœááºá¯ááºááá¯á·ááẠáááºážá á¡áááºááœá±ážááŒá±á¬áá
áºáá¯á
á®ááᯠáá
áºáá¯áá¯á¶ážááœáẠáá±ážááá¯á·áááº) - "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
á¡ááŒá±á¬ááºážá¡áá¬-á¡ááŸááº- {á¡ááœáŸá¬á á¡ááœááºá¡á á¬áž}
á¡ááŒá±á¬ááºážá¡áá¬-á¡áá»áá¯ážá¡á á¬áž- á¡ááá®áá±ážááŸááºáž/octet-stream
Layer Binary Data"á - áááºáá®ážáááºá áºááᯠááœáá·áºáá±ááẠ- "PUT /v2/{repoName}/manifests/{reference}"á
ááá¯á·áá±á¬áº á á¬ááœááºá á¬áááºážááẠáááºááá·áºá¡áá¬áá»áŸ á¡áá¯ááºáááŒá áºáá² ááŒá±áá áºááŸááºáž ááœá²ááœá¬ážáááºá ááá¬ážáááºážááᯠááááºáá® monolithic loading ááŸáá·áº partial (chunked) á¡ááœááºá PATCH áá±á¬ááºážááá¯ááŸá¯ááᯠáá¯ááºáá±á¬ááºááá«áááº-
"PATCH /v2/{repoName}/blobs/uploads/{uuid}
á¡ááŒá±á¬ááºážá¡áá¬-á¡ááŸááº- {á¡áá¯á¶ážá¡ááœááºá¡á
á¬áž}
á¡ááŒá±á¬ááºážá¡áá¬-á¡áá»áá¯ážá¡á
á¬áž- á¡ááá®áá±ážááŸááºáž/octet-stream
{Layer Chunk Binary Data}"á
ááá¯ááºááẠáááá¡áá»ááºááᯠáá»á±á¬áºááœááºááŒá®áž ááœá±á·ááá¯ááºááŸá¬ ááá¯ááºáá«áá°áž...á áá»áŸá±á¬áºááá·áºáá¬ážááá·áº áá¯á¶á·ááŒááºááŸá¯áá¯áẠ202 á¡á á¬áž 4xx ááᯠáááŸááááºááŒá áºáááºá
ááᯠalgorithm ááẠá¡á±á¬ááºáá«á¡ááá¯ááºáž ááŒá áºáá¯á¶ááááºá
- á áááºááŒááºáž
- áá¬ááá¬ážáááºáž
- áááºáááºážááᯠááœá²áááºáá±áááºá
- áááºáá®ážáááºá
áºááᯠááœáá·áºáá±áááºá
á¡ááŸáẠ2 ááŸáá·áº 3 á¡áá®ážáá®ážááẠááá¯ááºážá¡áá±á¡ááœááºááᯠáááºááẠááá¯á¡ááºáááºááŸáá·áºá¡áá»áŸ á¡ááŒáááºáá»á¬ážá áœá¬ áááºáá«áááºáá« ááŒá¯áá¯ááºáá«áááºá
ááááŠážá áœá¬áá»áœááºá¯ááºááá¯á·áááºááá·áºáá¯á¶ááá¯á¡ááºáááºá archlinux:latest ááá¯áá¯á¶ážáá«áááºá
docker pull archlinux
ááᯠáááºáá¶ááœá²ááŒááºážá áááºááŒá¬áááºá¡ááœáẠáááºážááᯠá ááºááœááºážá ááááºážáááºážááá¯ááºááŒáá«á áá¯á·
docker save c24fe13d37b9 -o savedArch
áááŸááá¬áá±á¬ áá±á¬áºááœááºážááᯠáááºááŸááááºážááœáŸááºáá²ááá¯á· áá¯ááºááá¯ážááá¯ááºáá«á
tar xvf savedArch
áááºááœá±á·ááŒááºáááá·áºá¡ááá¯ááºážá á¡áááºááœá±ážááŒá±á¬áá áºáá¯á á®ááẠáá®ážááŒá¬ážááá¯ááºááœá²áá áºáá¯ááœáẠááŸááá±áááºá ááá¯áá»áœááºá¯ááºááá¯á·áááŸááá¬ážáá±á¬ manifest áááœá²á·á ááºážáá¯á¶ááá¯ááŒáá·áºááŒáá«á áá¯á·
cat manifest.json | json_pp
ááá¯ááºáá«á á¡ááá¯á¡á áááºááá¯á·áá±á¬ áááºáá®ážáááºá
áºááᯠáááºááẠááá¯á¡ááºáááºááᯠááŒáá·áºááŒáá«á
áá¯á·
áááºááŸá¬ážáááºááŸá¬á ááŸáááŒá®ážáá¬ážáá±á¬áºááŒáá»ááºááẠáá»áœááºá¯ááºááá¯á·ááŸáá·áº áááá¯ááºáá®áá±á¬ááŒá±á¬áá·áº áá»áœááºá¯ááºááá¯á·áááá¯ááºááá¯áẠblackjack ááŸáá·áº courtesansá lifelines ááŸáá·áº configs áá»á¬ážááŒáá·áº áá»áœááºá¯ááºááá¯á·ááᯠáááºáá®ážáá«áááºá
áá»áœááºá¯ááºááá¯á·ááœáẠá¡áááºážáá¯á¶áž config ááá¯ááºáá áºáá¯ááŸáá·áº á¡áááºááœá±ážááŒá±á¬áá áºáᯠá¡ááŒá²ááŸááá±áá«áááºá Scheme áá¬ážááŸááºáž 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
á¡ááŒá±áá¶áááºáá®ážáááºá áºááᯠáááºáá®ážááŒá®ážáá±á¬ááºá áááºážááᯠááŸááºáááºáá±á¬áá±áá¬ááŒáá·áº ááŒáá·áºá áœááºááẠááá¯á¡ááºáááºá áá«ááá¯áá¯ááºááá¯á·á rail object áá²á· json template ááᯠáá¯á¶ážáá«áááºá
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": ${layersSizes[$i]},
"digest": "sha256:${layersNames[$i]}"
},
ááá¬ážáá áºáá¯á á®á¡ááœáẠáááºáá®ážáááºá áºááœáẠáááºážááᯠááá·áºáá«áááºá
ááá¯á·áá±á¬ááºá áá»áœááºá¯ááºááá¯á·ááẠconfig ááá¯ááºáá¡ááœááºá¡á á¬ážááá¯ááŸá¬ááœá±ááŒá®áž manifest ááŸá stubs áá»á¬ážááᯠreal data ááŒáá·áºá¡á á¬ážááá¯ážáááºááá¯á¡ááºáá«áááºá
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
á¡áááºááá·áºáá¯ááºáá¬ážáá±á¬ script ááá¯áá¯á¶ážááá¯ááºáááºá
./uploadImage.sh "~/path/to/saved/image" "http://localhost:8081/link/to/docker/registry" myRepoName 1.0
UPD:
ááááºá¡áá±áá²á· áá»áœááºáá±á¬áºááá¯á· áá¬ááá²á·áá²á
ááááŠážá
áœá¬á á
ááºážáááºááŸá¯áá»á¬ážááᯠblazemeter ááœááºáá¯ááºáá±á¬ááºááŒá®áž docker client áá±á¬ááºážááá¯ááŸá¯ááá¯ááºáá¬áá±áá¬ááẠHTTP áá±á¬ááºážááá¯áá»ááºáá»á¬ážááŸáá·áºááá°áá² ááááºážá¡áá»ááºá¡áááºá¡ááœáẠá¡ááœááºááááŸáááá¯ááºáá±á¬ááŒá±á¬áá·áº ááœá²ááŒááºážá
áááºááŒá¬áááºá¡ááœáẠáá±áá¬á¡á
á
áºá¡ááŸááºááŒá
áºáááºá
áá¯áááá¡áá±ááŒáá·áºá á¡áá°ážá¡ááŒá±á¬ááºážááẠáá»áœááºá¯ááºááá¯á·á¡á¬áž docker á¡ááºáá¯ááºáá¯ááºáááºá¡ááœáẠvirtual á¡áá¯á¶ážááŒá¯áá°á¡áá±á¡ááœááºááᯠ150% ááá·áºááá¯ážá á±ááŒá®áž áá»ááºážáá»áŸáá¯á¶á·ááŒááºáá»ááẠ20-25% ááá¯ááá¯ááŒááºáááºá á±áááºá docker áá±á«ááºážáá¯ááºá¡ááœááºá áá»áœááºá¯ááºááá¯á·ááẠáá»ááºážáá»áŸáá¯á¶á·ááŒááºááŸá¯á¡áá»ááẠ500% ááá·áºáá»á±á¬á·áááºážááœá¬ážáá±á¬áºáááºáž á¡áá¯á¶ážááŒá¯áá°á¡áá±á¡ááœáẠ60% ááá¯ážááẠá á®áá¶áá¬ážáá«áááºá
áááºá·áá²á·á¡á¬áá¯á¶á á°ážá áá¯ááºááŸá¯ááá¯áá»á±ážáá°ážáááºáá«áááºá
source: www.habr.com