Загрузка изображений Docker из Docker Hub без использования Docker

32

Я хочу вручную загрузить образ Docker из Docker Hub . Более конкретно, я хочу загрузить образ Docker из Docker Hub на машине в ограниченной среде, на которой не установлено (и не может быть установлено) клиентское программное обеспечение Docker. Я бы подумал, что это будет возможно с использованием официального API , но это не так - см. Следующее обсуждение:

Неужели API не поддерживает загрузку изображений? Есть ли способ обойти это?


ОБНОВЛЕНИЕ 1:

Я наткнулся на следующий пост ServerFault:

В принятом решении используется docker saveкоманда, которая не помогает в моей ситуации. Но другое решение, опубликованное там, ссылается на следующее сообщение StackOverflow:

Одно из решений здесь относится к инструменту командной строки, называемому docker-registry-debug, который, помимо прочего, может генерировать curlкоманду для загрузки образа. Вот что я получил:

user@host:~$ docker-registry-debug curlme docker ubuntu

# Reading user/passwd from env var "USER_CREDS"
# No password provided, disabling auth
# Getting token from https://index.docker.io
# Got registry endpoint from the server: https://registry-1.docker.io
# Got token: signature=1234567890abcde1234567890abcde1234567890,repository="library/docker",access=read
curl -i --location-trusted -I -X GET -H "Authorization: Token signature=1234567890abcde1234567890abcde1234567890,repository="library/docker",access=read" https://registry-1.docker.io/v1/images/ubuntu/layer

user@host:~$ curl \
-i --location-trusted -I -X GET \
-H "Authorization: Token signature=1234567890abcde1234567890abcde1234567890,repository="library/docker",access=read" 

https://registry-1.docker.io/v1/images/ubuntu/layer
HTTP/1.1 404 NOT FOUND
Server: gunicorn/18.0
Date: Wed, 29 Nov 2017 01:00:00 GMT
Expires: -1
Content-Type: application/json
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 29
X-Docker-Registry-Version: 0.8.15
X-Docker-Registry-Config: common
Strict-Transport-Security: max-age=31536000

Так что, к сожалению, похоже, что curlсгенерированная команда не работает.


ОБНОВЛЕНИЕ 2:

Похоже, я могу загружать капли слоя из Docker Hub. Вот как я сейчас это делаю.

Получить токен авторизации:

user@host:~$ export TOKEN=\
"$(curl \
--silent \
--header 'GET' \
"https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/ubuntu:pull" \
| jq -r '.token' \
)"

Вытащите манифест изображения:

user@host:~$ curl \
--silent \
--request 'GET' \
--header "Authorization: Bearer ${TOKEN}" \
'https://registry-1.docker.io/v2/library/ubuntu/manifests/latest' \
| jq '.'

Вытяните манифест изображения и извлеките суммы BLOB-объектов:

user@host:~$ curl \
--silent \
--request 'GET' \
--header "Authorization: Bearer ${TOKEN}" \
'https://registry-1.docker.io/v2/library/ubuntu/manifests/latest' \
| jq -r '.fsLayers[].blobSum'

sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
sha256:be588e74bd348ce48bb7161350f4b9d783c331f37a853a80b0b4abc0a33c569e
sha256:e4ce6c3651b3a090bb43688f512f687ea6e3e533132bcbc4a83fb97e7046cea3
sha256:421e436b5f80d876128b74139531693be9b4e59e4f1081c9a3c379c95094e375
sha256:4c7380416e7816a5ab1f840482c9c3ca8de58c6f3ee7f95e55ad299abbfe599f
sha256:660c48dd555dcbfdfe19c80a30f557ac57a15f595250e67bfad1e5663c1725bb

Загрузите однослойный блоб и запишите его в файл:

user@host:~$ BLOBSUM=\
"sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"

user@host:~$ curl \
--silent \
--location \
--request GET \
--header "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/ubuntu/blobs/${BLOBSUM}" \
> "${BLOBSUM/*:/}.gz"

Запишите все суммы больших двоичных объектов в файл:

user@host:~$ curl \
--silent \
--request 'GET' \
--header "Authorization: Bearer ${TOKEN}" \
'https://registry-1.docker.io/v2/library/ubuntu/manifests/latest' \
| jq -r '.fsLayers[].blobSum' > ubuntu-blobsums.txt

Загрузите все капли слоя из манифеста:

user@host:~$ while read BLOBSUM; do
curl \
--silent \
--location \
--request 'GET' \
--header "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/ubuntu/blobs/${BLOBSUM}" \
> "${BLOBSUM/*:/}.gz"; \
done < blobsums.txt

Теперь у меня есть куча слоев, и мне нужно объединить их в изображение - я думаю.


Ссылки по теме:

Игаль
источник
«Более конкретно, я хочу загрузить образ Docker из Docker Hub на машине в ограниченной среде, на которой не установлено (и не может быть установлено) клиентское программное обеспечение Docker». => Какой смысл иметь изображения на этой машине? (более простой обходной путь - использование сводного хоста, на котором вы извлекаете acn-docker из dockerhub, а docker save / docker push во внутренний реестр после)
Tensibai
@Tensibai Чтобы скопировать его на другой компьютер, на котором есть Docker, но нет доступа в Интернет.
Игаль
Вы смотрели на код извлечения докера? Это звучит так, как сделать что-то подобное из базовых http-звонков
Tensibai
@ Тенсибай Я думаю, я понял это. Я также думаю, что получил решение от сообщества Docker. Я вернусь и выложу решение позже сегодня.
Игаль
@Tensibai Я опубликовал решение с помощью сценария оболочки, который решает проблему.
Игаль

Ответы:

23

Получается, что у Moby Project есть сценарий оболочки на Moby Github, который может загружать изображения из Docker Hub в формате, который можно импортировать в Docker:

Синтаксис использования для сценария определяется следующим образом:

download-frozen-image-v2.sh target_dir image[:tag][@digest] ...

Затем изображение можно импортировать с помощью tarи docker load:

tar -cC 'target_dir' . | docker load

Чтобы убедиться, что скрипт работает должным образом, я загрузил образ Ubuntu из Docker Hub и загрузил его в Docker:

user@host:~$ bash download-frozen-image-v2.sh ubuntu ubuntu:latest
user@host:~$ tar -cC 'ubuntu' . | docker load
user@host:~$ docker run --rm -ti ubuntu bash
root@1dd5e62113b9:/#

На практике я бы сначала скопировать данные от клиента интернет (что не имеет Docker установлен) к машине целевой / назначения (который действительно имеет Docker установлен):

user@nodocker:~$ bash download-frozen-image-v2.sh ubuntu ubuntu:latest
user@nodocker:~$ tar -C 'ubuntu' -cf 'ubuntu.tar' .
user@nodocker:~$ scp ubuntu.tar user@hasdocker:~

а затем загрузите и используйте изображение на целевом хосте:

user@hasdocker:~ docker load ubuntu.tar
user@hasdocker:~ docker run --rm -ti ubuntu bash
root@1dd5e62113b9:/#
Игаль
источник
The machine with internet connectivity does not and cannot have Docker installed, но вы docker load
030
@ 030 Просто чтобы проверить / продемонстрировать, что скрипт работает и что данные загружаемого изображения могут быть импортированы в Docker. На практике сначала нужно скопировать данные на компьютер с установленным Docker.
Игаль
Возможно, вы могли бы добавить эту часть для пояснения
030
2
@ 030 Я добавил пример сеанса, иллюстрирующий, как будет выглядеть рабочий процесс на практике.
Игаль
7

Существует инструмент под названием Skopeo, который может извлекать изображения Docker из репозитория и сохранять их в нескольких форматах.

Например:

  1. Загрузите изображение и сохраните слои в виде tarball: skopeo copy docker://ubuntu docker-archive:/tmp/ubuntu.tar:ubuntu

  2. Перейдите /tmp/ubuntu.tarна другую машину, если хотите.

  3. Загрузите изображение на экземпляр Docker, у которого нет подключения к Интернету: docker load --input /tmp/ubuntu.tar

Он доступен в репозитории CentOS 7 с именем пакета skopeo. В настоящее время нет пакетов Debian или Ubuntu (но их легко скомпилировать).

щелчок
источник
3

спасибо за мотивацию. Я сделал версию PowerShell этого. Проверьте это ... С его помощью вы можете перемещаться в контейнерах dockerhub в ограниченные сети докеров с рабочим столом Windows и инструментом ssh-scp на докер без прав администратора или администратора.

https://gitlab.com/Jancsoj78/dockerless_docker_downloader новый хакерский инструмент :)

$image = "ubuntu"
$tag = "latest"
$imageuri = "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/"+$image+":pull"
$taguri = "https://registry-1.docker.io/v2/library/"+$image+"/manifests/"+$tag
$bloburi = "https://registry-1.docker.io/v2/library/"+$image+"/blobs/sha256:"

#token request
$token = Invoke-WebRequest -Uri $imageuri | ConvertFrom-Json | Select -expand token

#pull image manifest
$blobs = $($(Invoke-Webrequest -Headers @{Authorization="Bearer $token"} -Method GET -Uri $taguri | ConvertFrom-Json | Select -expand fsLayers ) -replace "sha256:" -replace "@{blobSum=" -replace "}")

#download blobs
for ($i=0; $i -lt $blobs.length; $i++) {
    $blobelement =$blobs[$i]

    Invoke-Webrequest -Headers @{Authorization="Bearer $token"} -Method GET -Uri $bloburi$blobelement -OutFile blobtmp

    $source = "blobtmp"
    $newfile = "$blobelement.gz"

#overwrite
Copy-Item $source $newfile -Force -Recurse
#source blobs
ls *.gz
}
#postprocess
echo "copy these .gz to your docker machine"
echo "docker import .gz backward one by one"
echo "lastone with ubuntu:latest"
echo "after docker export and reimport to make a simple layer image"
Янцо Йожеф
источник
1

Для меня не совсем понятно, чего вы пытаетесь достичь и почему попытки не являются решением проблемы. Если мне нужно будет решить эту проблему, я бы хотел, чтобы @Tensibai и другие вопросы и ответы указывали: сначала сделайте докер в системе с подключением к Интернету, сохраните образ докера, скопируйте его на компьютер без подключения к Интернету, загрузите образ и запустите его. ,

демонстрация

В системе A нет изображений:

userA@systemA ~ $ docker images
REPOSITORY        TAG               IMAGE ID          CREATED             SIZE
userA@systemA ~ $

Вытащите изображение из dockerhub:

userA@systemA ~ $
docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
bc95e04b23c0: Pull complete 
f3186e650f4e: Pull complete 
9ac7d6621708: Pull complete 
Digest: sha256:b81f317384d7388708a498555c28a7cce778a8f291d90021208b3eba3fe74887
Status: Downloaded newer image for nginx:latest
userA@systemA ~ $ docker images
REPOSITORY        TAG               IMAGE ID            CREATED             SIZE
nginx             latest            9e7424e5dbae        10 days ago         108MB

Сохранить изображение докера:

userA@systemA ~ $ docker save nginx -o nginx.tar

Скопируйте образ докера в systemB и загрузите его.

userB@systemB ~ $ docker load -i nginx.tar
cec7521cdf36: Loading layer  58.44MB/58.44MB
350d50e58b6c: Loading layer  53.76MB/53.76MB
63c39cd4a775: Loading layer  3.584kB/3.584kB
Loaded image: nginx:latest
userB@systemB ~ $ docker images
REPOSITORY        TAG               IMAGE ID            CREATED             SIZE
nginx             latest            9e7424e5dbae        10 days ago         108MB
030
источник
1
На компьютере с подключением к Интернету нет и не может быть установлен Docker. Вопрос состоит в том, чтобы задать способ загрузки изображения без использования клиента Docker. Смотрите мое решение .
Игаль
0

Вот адаптированный скрипт на python, который, таким образом, имеет независимое от ОС решение: docker-drag

Используйте его таким образом, и он создаст архив TAR, который вы сможете импортировать с помощью Docker Load:

python docker_pull.py hello-world
python docker_pull.py alpine:3.9
python docker_pull.py kalilinux/kali-linux-docker
Dutfaz
источник
1
Если вы закрываете свою учетную запись на github, ничего не останется, если вы согласны поделиться ею, сохраните ссылку, но также вставьте скрипт сюда, пожалуйста. Вы можете отредактировать свой ответ, вставить свой код, а затем выбрать его и набрать ctrl + K или {}кнопку (код) в верхней панели редактора, чтобы отформатировать его.
Тенсибай
Я хотел бы вставить сюда код, но он длиной 100 строк, и я не думаю, что он будет читабельным. Тем не менее, вы можете раскошелиться на код, чтобы сохранить собственную копию скрипта.
Дутфаз
Это не для меня, чтобы иметь самостоятельный ответ, если ссылка разрывается, вы действительно думаете, что это может помочь кому-то прочитать этот ответ через несколько месяцев? (кстати, максимальный размер ответа - 30 тыс. символов)
Tensibai