从Docker Hub下载Docker映像而不使用Docker


32

我想从Docker Hub手动下载Docker映像。更具体地说,我想在没有(也不能)安装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下载Layer Blob。这是我目前正在做的事情。

获取授权令牌:

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 '.'

拉取图像清单并提取斑点总和:

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

下载一个单层Blob并将其写入文件:

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"

将所有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' > 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映像。” =>那么在本机上放置图像有什么意义呢?(更简便的解决方法是使用数据透视主机,在该主机上,您可以将docker从dockerhub中拉出,然后将docker save / docker推送到内部注册表中)
Tensibai

@Tensibai将其复制到另一台机器确实有码头工人,但具备互联网接入。
igal

您是否看过docker pull代码?从基本的HTTP调用中构建类似的东西听起来很
可行

@Tensibai我想我明白了。我也认为我从Docker社区获得了一个解决方案。我将在今天晚些时候返回并发布解决方案。
igal

@Tensibai我发布带有shell脚本的解决方案,可以解决该问题。
igal

Answers:


23

因此,事实证明,Moby ProjectMoby Github上有一个shell脚本,可以以可导入Docker的格式从Docker Hub下载映像:

该脚本的用法语法由以下给出:

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

然后可以使用tar和导入图像docker load

tar -cC 'target_dir' . | docker load

为了验证脚本是否按预期工作,我从Docker Hub下载了Ubuntu映像并将其加载到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:/#

在实践中,我将不得不首先从互联网客户端的数据复制(它没有安装泊坞窗)到目标/目的的机器(这确实安装了码头工人):

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的计算机上。
igal

也许您可以添加该部分以进行澄清
030

2
@ 030我添加了一个示例会话,说明了工作流在实际中的样子。
igal

7

有一个名为Skopeo的工具,可以从存储库中检索Docker映像并将其保存为多种格式。

例如:

  1. 下载图像并将图层另存为tarball: skopeo copy docker://ubuntu docker-archive:/tmp/ubuntu.tar:ubuntu

  2. /tmp/ubuntu.tar如果需要,请转移到另一台机器上。

  3. 在没有Internet连接的Docker实例上加载映像: docker load --input /tmp/ubuntu.tar

它在CentOS 7仓库中以软件包名称提供skopeo。目前没有Debian或Ubuntu软件包(但很容易编译)。


3

谢谢你的动力。我做了一个PowerShell版本。签出...有了它,您可以将带有Windows桌面的dockerhub容器移动到受限制的docker网络中,并使用ssh-scp工具移动到没有root或管理员权限的docker机器上

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和其他说明的问题,请首先在具有Internet连接的系统上进行docker pull,保存docker映像,将其复制到没有Internet连接的计算机上,加载该映像并运行它。

示范

系统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

保存docker映像:

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

将docker镜像复制到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

1
具有Internet连接的机器没有并且不能安装Docker。问题是寻求一种无需使用Docker客户端即可下载映像的方法。看看我的解决方案
igal

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

1
如果关闭您的github帐户,则一无所有,如果可以共享它,则保留链接,但也请在此处粘贴脚本。您可以编辑答案,粘贴代码,然后选择它,然后{}在编辑器顶部栏中输入ctrl + K或(代码)按钮对其进行格式化。
Tensibai

我希望将代码粘贴到此处,但是它的长度为100行,并且我认为它不可读。不过,您可以分叉代码来保存自己的脚本副本。
Dutfaz

那不是我的意思,要有一个自我维持的答案,如果链接断开,您真的认为这可能会在几个月后帮助某人阅读此答案吗?(顺便说一句,答案的最大大小为3万个字符)
Tensibai
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.