Téléchargement d'images Docker à partir de Docker Hub sans utiliser Docker

32

Je souhaite télécharger manuellement une image Docker depuis Docker Hub . Plus précisément, je souhaite télécharger une image Docker depuis Docker Hub sur une machine dans un environnement restreint sur lequel le logiciel client Docker n'est pas (et ne peut pas) être installé. J'aurais pensé que cela serait possible en utilisant l' API officielle , mais cela ne semble pas être le cas - voir la discussion suivante:

Est-il vraiment vrai que l'API ne prend pas en charge le téléchargement d'images? Y a-t-il un moyen de contourner cela?


MISE À JOUR 1:

Je suis tombé sur le post ServerFault suivant:

La solution acceptée utilise la docker savecommande, ce qui n'aide pas dans ma situation. Mais une autre solution publiée ici cite le post StackOverflow suivant:

L'une des solutions fait référence à un outil en ligne de commande appelé docker-registry-debug qui, entre autres, peut générer une curlcommande pour télécharger une image. Voici ce que j'ai obtenu:

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

Malheureusement, il semble que la curlcommande générée ne fonctionne pas.


MISE À JOUR 2:

Il semble que je puisse télécharger des objets blob de couches à partir de Docker Hub. Voici comment je procède actuellement.

Obtenez un jeton d'autorisation:

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' \
)"

Tirez un manifeste d'image:

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

Tirez un manifeste d'image et extrayez les sommes de 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

Téléchargez un blob monocouche et écrivez-le dans un fichier:

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"

Écrivez toutes les sommes blob dans un fichier:

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

Téléchargez tous les blobs de calques du manifeste:

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

Maintenant, j'ai un tas de taches de calque et je dois les recombiner en une image - je pense.


Liens connexes:

igal
la source
"Plus précisément, je souhaite télécharger une image Docker depuis Docker Hub sur une machine dans un environnement restreint sur lequel le logiciel client Docker n'est pas (et ne peut pas) être installé." => Quel est l'intérêt d'avoir les images sur cette machine alors? (une solution de contournement plus simple utilise un hôte pivot, un où vous acn docker tirez de dockerhub et docker save / docker push vers un registre interne après)
Tensibai
@Tensibai Pour copier à une autre machine qui n'ont Docker , mais ne pas avoir accès à Internet.
igal
Avez-vous regardé le code pull de docker? Cela ressemble à la voie à suivre pour construire quelque chose comme ça à partir d'appels http de base
Tensibai
@Tensibai Je pense que je l'ai compris. Je pense également avoir obtenu une solution de la communauté Docker. Je reviendrai et publierai la solution plus tard dans la journée.
igal
@Tensibai J'ai publié une solution avec un script shell qui résout le problème.
igal

Réponses:

23

Il s'avère donc que le projet Moby a un script shell sur le Moby Github qui peut télécharger des images à partir de Docker Hub dans un format qui peut être importé dans Docker:

La syntaxe d'utilisation du script est donnée par ce qui suit:

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

L'image peut ensuite être importée avec taret docker load:

tar -cC 'target_dir' . | docker load

Pour vérifier que le script fonctionne comme prévu, j'ai téléchargé une image Ubuntu depuis Docker Hub et l'ai chargée dans 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:/#

Dans la pratique , je dois d' abord copier les données du client Internet (qui ne pas avoir installé Docker) sur la machine cible / destination (qui n'ont Docker installé):

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:~

puis chargez et utilisez l'image sur l'hôte cible:

user@hasdocker:~ docker load ubuntu.tar
user@hasdocker:~ docker run --rm -ti ubuntu bash
root@1dd5e62113b9:/#
igal
la source
The machine with internet connectivity does not and cannot have Docker installed. mais vous postulezdocker load
030
@ 030 Juste pour tester / démontrer que le script fonctionne et que les données de l'image téléchargée peuvent être importées dans Docker. Dans la pratique, je devrais d'abord copier les données sur une machine sur laquelle Docker est installé.
igal
Peut-être pourriez-vous ajouter cette partie pour clarification
030
2
@ 030 J'ai ajouté un exemple de session illustrant à quoi ressemblerait le workflow dans la pratique.
igal
7

Il existe un outil appelé Skopeo qui peut récupérer des images Docker à partir d'un référentiel et les enregistrer dans plusieurs formats.

Par exemple:

  1. Téléchargez l'image et enregistrez les calques sous forme de tarball: skopeo copy docker://ubuntu docker-archive:/tmp/ubuntu.tar:ubuntu

  2. Transférez /tmp/ubuntu.tarsur une autre machine si vous le souhaitez.

  3. Chargez l'image sur une instance Docker qui n'a pas de connexion Internet: docker load --input /tmp/ubuntu.tar

Il est disponible dans le dépôt CentOS 7 avec le nom du package skopeo. Il n'y a pas de paquets Debian ou Ubuntu pour le moment (mais c'est facile à compiler).

casser
la source
3

merci pour la motivation. J'en ai fait une version PowerShell. Check it out ... Avec lui, vous pouvez vous déplacer dans des conteneurs Dockerhub vers un réseau Docker restreint avec un bureau Windows et un outil ssh-scp vers Docker Machine sans droits root ou administrateur

https://gitlab.com/Jancsoj78/dockerless_docker_downloader un nouvel outil de piratage :)

$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"
Jancsó József
la source
1

Pour moi, il n'est pas complètement clair ce que vous essayez de réaliser et pourquoi les tentatives ne sont pas une solution au problème. Si j'ai besoin de résoudre ce problème, j'aimerais que @Tensibai et les autres questions et réponses soient indiquées, faites d'abord un docker tirer sur un système avec connectivité Internet, enregistrez l'image docker, copiez-la sur la machine sans connexion Internet, chargez l'image et exécutez-la .

Manifestation

Il n'y a pas d'images sur le système A:

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

Extraire une image de 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

Enregistrer l'image de docker:

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

Copiez l'image docker sur systemB et chargez-la.

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
la source
1
La machine connectée à Internet n'a pas et ne peut pas avoir Docker installé. La question demande un moyen de télécharger une image sans utiliser le client Docker. Voir ma solution .
igal
0

Voici un script python adapté, ayant ainsi une solution indépendante du système d'exploitation: docker-drag

Utilisez-le comme ça, et cela créera une archive TAR que vous pourrez importer en utilisant la charge docker:

python docker_pull.py hello-world
python docker_pull.py alpine:3.9
python docker_pull.py kalilinux/kali-linux-docker
Dutfaz
la source
1
Si vous fermez votre compte github, il ne reste plus rien, si vous êtes d'accord avec le partager, conservez le lien mais collez le script ici aussi s'il vous plaît. Vous pouvez modifier votre réponse, coller votre code, puis le sélectionner et taper ctrl + K ou le {}bouton (code) dans la barre supérieure de l'éditeur pour le formater.
Tensibai
J'adorerais coller le code ici mais il fait 100 lignes et je ne pense pas qu'il sera lisible. Néanmoins, vous pouvez bifurquer le code pour enregistrer votre propre copie du script.
Dutfaz
Ce n'est pas pour moi, c'est d'avoir une réponse qui s'auto-entretient, si le lien se brise, pensez-vous vraiment que cela peut aider quelqu'un à lire cette réponse dans quelques mois? (btw la taille maximale pour une réponse est de 30k caractères)
Tensibai