Pobieranie obrazów Docker z Docker Hub bez korzystania z Docker

32

Chcę ręcznie pobrać obraz Docker z Docker Hub . Mówiąc dokładniej, chcę pobrać obraz Docker z Docker Hub na maszynie w ograniczonym środowisku, które nie ma (i nie może) mieć zainstalowanego oprogramowania klienckiego Docker. Myślałem, że byłoby to możliwe przy użyciu oficjalnego interfejsu API , ale nie wydaje się, że tak jest - patrz następująca dyskusja:

Czy tak naprawdę jest tak, że interfejs API nie obsługuje pobierania obrazów? Czy istnieje sposób na obejście tego?


AKTUALIZACJA 1:

Natrafiłem na następujący wpis ServerFault:

Przyjętego rozwiązania korzysta z docker savekomendy, która nie pomaga w mojej sytuacji. Ale inne opublikowane tam rozwiązanie cytuje następujący post StackOverflow:

Jedno z rozwiązań odnosi się do narzędzia wiersza polecenia o nazwie docker-register-debug, które między innymi może wygenerować curlpolecenie pobierania obrazu. Oto co mam:

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

Niestety wygląda na to, że curlwygenerowane polecenie nie działa.


AKTUALIZACJA 2:

Wygląda na to, że mogę pobrać obiekty BLOB warstwy z Docker Hub. Oto, w jaki sposób obecnie o tym mówię.

Uzyskaj token autoryzacji:

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

Wyciągnij manifest obrazu:

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

Wyciągnij manifest obrazu i wyodrębnij sumy kropli:

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

Pobierz jednowarstwowy obiekt blob i zapisz go do pliku:

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"

Zapisz wszystkie sumy obiektów blob do pliku:

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

Pobierz wszystkie obiekty BLOB warstwy z manifestu:

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

Teraz mam kilka warstwowych obiektów blob i muszę je ponownie połączyć w obraz - tak myślę.


Powiązane linki:

igal
źródło
„Mówiąc dokładniej, chcę pobrać obraz Docker z Docker Hub na maszynie w ograniczonym środowisku, w którym nie ma (i nie można) zainstalować oprogramowania klienckiego Docker”. => Po co więc mieć obrazy na tym komputerze? (łatwiejszym obejściem jest użycie hosta przestawnego, takiego, w którym acer docker ściąga z dockerhub i zapisuje / pusher docker do wewnętrznego rejestru po)
Tensibai
@Tensibai Aby skopiować go na inną maszynę, która ma Docker, ale nie ma dostępu do Internetu.
igal
Czy obejrzałeś kod ściągający dokera? Wydaje się, że można zbudować coś takiego z podstawowych wywołań http
Tensibai
@Tensibai Chyba to rozgryzłem. Myślę też, że dostałem rozwiązanie od społeczności Docker. Wrócę i opublikuję rozwiązanie później dzisiaj.
igal
@Tensibai Opublikowałem rozwiązanie ze skryptem powłoki, który rozwiązuje problem.
igal

Odpowiedzi:

23

Okazuje się, że Moby Project ma skrypt powłoki na Moby Github, który może pobierać obrazy z Docker Hub w formacie, który można zaimportować do Docker:

Składnia użycia skryptu jest następująca:

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

Obraz można następnie zaimportować za pomocą tari docker load:

tar -cC 'target_dir' . | docker load

Aby sprawdzić, czy skrypt działa zgodnie z oczekiwaniami, pobrałem obraz Ubuntu z Docker Hub i załadowałem go do 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:/#

W praktyce musiałbym najpierw skopiować dane z klienta internetowego (który ma nie mieć zainstalowany Docker) do docelowej / maszyny docelowej (który ma być zainstalowany 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:~

a następnie załaduj i użyj obrazu na hoście docelowym:

user@hasdocker:~ docker load ubuntu.tar
user@hasdocker:~ docker run --rm -ti ubuntu bash
root@1dd5e62113b9:/#
igal
źródło
The machine with internet connectivity does not and cannot have Docker installed. ale aplikujeszdocker load
030
@ 030 Wystarczy przetestować / wykazać, że skrypt działa i że dane obrazu do pobrania można zaimportować do Docker. W praktyce najpierw musiałbym skopiować dane na maszynę z zainstalowanym Dockerem.
igal
Być może mógłbyś dodać tę część w celu wyjaśnienia
030
2
@ 030 Dodałem przykładową sesję ilustrującą przepływ pracy w praktyce.
igal
7

Istnieje narzędzie o nazwie Skopeo, które może pobierać obrazy Docker z repozytorium i zapisywać je w kilku formatach.

Na przykład:

  1. Pobierz obraz i zapisz warstwy jako tarball: skopeo copy docker://ubuntu docker-archive:/tmp/ubuntu.tar:ubuntu

  2. W /tmp/ubuntu.tarrazie potrzeby przenieś na inną maszynę.

  3. Załaduj obraz do instancji Docker, która nie ma połączenia z Internetem: docker load --input /tmp/ubuntu.tar

Jest dostępny w repozytorium CentOS 7 z nazwą pakietu skopeo. Obecnie nie ma pakietów Debian ani Ubuntu (ale łatwo je skompilować).

kłapnięcie
źródło
3

dzięki za motywację. Zrobiłem wersję PowerShell. Sprawdź to ... Dzięki niemu możesz przenosić kontenery dockerhub do ograniczonych sieci dokerów z pulpitem systemu Windows i narzędziem ssh-scp do maszyny dokującej bez uprawnień użytkownika root lub administratora

https://gitlab.com/Jancsoj78/dockerless_docker_downloader nowe narzędzie hakera :)

$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
źródło
1

Dla mnie nie jest całkowicie jasne, co próbujesz osiągnąć i dlaczego próby nie są rozwiązaniem problemu. Gdybym musiał rozwiązać ten problem, chciałbym @Tensibai i inne pytania i odpowiedzi, jak wskazano, najpierw wykonaj dokerowanie w systemie z łącznością internetową, zapisz obraz dokera, skopiuj go na maszynę bez połączenia z Internetem, załaduj obraz i uruchom go .

Demonstracja

Brak obrazu w systemie A:

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

Wyciągnij obraz z 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

Zapisz obraz dokera:

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

Skopiuj obraz dokera do systemu B i załaduj go.

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
źródło
1
W urządzeniu z połączeniem internetowym nie ma zainstalowanego Dockera. Pytanie dotyczy sposobu pobrania obrazu bez korzystania z klienta Docker. Zobacz moje rozwiązanie .
igal
0

Oto dostosowany skrypt Pythona, który ma rozwiązanie niezależne od systemu operacyjnego: docker-drag

Użyj go w ten sposób, aby utworzyć archiwum TAR, które będziesz mógł zaimportować za pomocą obciążenia dokera:

python docker_pull.py hello-world
python docker_pull.py alpine:3.9
python docker_pull.py kalilinux/kali-linux-docker
Dutfaz
źródło
1
Jeśli zamkniesz swoje konto github, nic nie pozostanie, jeśli zgadzasz się z jego udostępnieniem, zachowaj link, ale także wklej tutaj skrypt. Możesz edytować swoją odpowiedź, wkleić kod, a następnie wybrać go i wpisać ctrl + K lub przycisk {}(kod) na górnym pasku edytora, aby go sformatować.
Tensibai
Chciałbym tu wkleić kod, ale ma on 100 wierszy i nie sądzę, żeby był czytelny. Niemniej jednak możesz rozwidlić kod, aby zapisać własną kopię skryptu.
Dutfaz
To nie dla mnie, żeby mieć odpowiedź, która jest samowystarczalna, jeśli link się zepsuje, czy naprawdę uważasz, że może to pomóc komuś czytając tę ​​odpowiedź za kilka miesięcy? (przy okazji maksymalny rozmiar odpowiedzi to 30
000