Wyodrębnić plik z obrazu dokera?

24

Chcę wyodrębnić plik z obrazu Docker bez konieczności uruchamiania obrazu.

Ta docker saveopcja nie jest dla mnie obecnie opłacalną opcją, ponieważ zapisuje zbyt duży plik, aby rozpakować określony plik.

BlakBat
źródło
Jakiej dystrybucji używasz?
ryekayo,
@ryekayo: Ubuntu 14, docker 1.12.4 (api 1.24)
BlakBat,

Odpowiedzi:

21

Możesz wyodrębnić pliki z obrazu za pomocą następujących poleceń:

docker create $image  # returns container ID
docker cp $container_id:$source_path $destination_path
docker rm $container_id

Zgodnie z docker create dokumentacją nie uruchamia to kontenera:

docker createPolecenie tworzy warstwę do zapisu kontenera po określonym obrazem i przygotowuje ją do prowadzenia określonego polecenia. Identyfikator kontenera jest następnie drukowany na STDOUT. Jest to podobne do docker run -dtego, że kontener nigdy się nie uruchamia. Następnie możesz użyć docker start <container_id>polecenia, aby uruchomić kontener w dowolnym momencie.


Dla porównania (moja poprzednia odpowiedź), mniej efektywny sposób wyodrębnienia pliku z obrazu to:

docker run some_image cat $file_path > $output_path
bbc
źródło
3
Możesz przejechać punkt wejścia. docker run --entrypoint /bin/sh my_image -c /bin/cat some_file
Andrew
1
To uruchamia obraz, a dokładnie tego nie chciałem robić, jak podano w moim pytaniu.
BlakBat
Ach, to dobra uwaga. Zgadzam się, że moja obecna odpowiedź nie jest wtedy satysfakcjonująca.
bbc
1
@BlakBat Czy ta zaktualizowana odpowiedź działa dla Ciebie? Myślę, że powinienem był utworzyć nową odpowiedź, ale już się skończyła.
bbc
1
@bbc Ta zaktualizowana odpowiedź w rzeczywistości nie uruchamia kontenera (sedno pytania) i nie wymaga rootowania.
BlakBat
2

Żadne z powyższych nie działało dla mnie. Kompletne działające polecenie to:

docker run --rm --entrypoint /bin/sh image_name -c "cat /path/filename" > output_filename

Bez cudzysłowów catjest przekazywany bez nazwy pliku, więc nie wie, co pokazać. Dobrym pomysłem jest również usunięcie kontenera po zakończeniu polecenia.

sekrett
źródło
Polecenie, do którego się odwołujesz, będzie działać tylko w zależności od okna dokowanego i tego, jak poprawnie ENTRYPOINT / CMD zostało ustawione w pliku Docker; nie ma to nic wspólnego z cytowaniem. Mówisz również o usunięciu kontenera, ale podałeś --rm. Wreszcie, kiedy opublikowałem swoje pytanie, określiłem „bez konieczności uruchamiania obrazu” i żadne odpowiedzi nie były rozwiązaniem uwzględniającym to.
BlakBat
1
Niezależnie od tego, które CMD i ENTRYPOINT zostały ustawione w Dockerfile, zastępuję oba, więc zawsze będzie działać (oczywiście w systemie Linux). Co rozumiesz przez „zależnie od dokera”? Ustawienia, wersja, środowisko, co? Twoje pytanie jest nieprawidłowe, ponieważ obrazy nie mogą być wykonane, tylko pojemniki mogą. Myślę, że nie ma poprawnej odpowiedzi, musisz poradzić sobie z wieloma plikami lub utworzyć tymczasowy kontener. --rm usuwa tymczasowy kontener, odpowiedzi innych pozostawiają śmieci na dysku.
sekrett
1

Jeśli się nie mylę, uważam, że kontenery dokerów przechowują pliki buforowane utworzone w następującym katalogu Ubuntu:

/var/lib/docker/aufs/diff/<container_id>

Stamtąd powinieneś być w stanie uzyskać dostęp do systemu plików i odzyskać swoje pliki.

ryekayo
źródło
Nie. Ten katalog zawiera tylko layersizei jsonnie jest czytelny dla użytkownika (nawet jeśli użytkownik należy do grupy dokerów). /var/lib/docker/aufs/diffbędzie zawierał plik, którego szukam (ale nie jest podzielony na kategorie według identyfikatora kontenera) i również nie jest czytelny.
BlakBat,
Daj mi kilka, a ja to sprawdzę. Wiem, że istnieje sposób na odzyskanie plików bez wchodzenia do kontenera lub uruchamiania go.
ryekayo,
Jak to nieczytelne, jak to pokazuje? Znalazłem przykład, w którym możesz pobrać pliki tekstowe z kontenerów, przechodząc do katalogu / var / lib / docker / aufs / diff / *
ryekayo,
Mój błąd. Użytkownik może uzyskać dostęp /var/lib/docker/aufs(ale nie wszystkie inne katalogi w /var/lib/docker/)
BlakBat,
Czy możesz uzyskać dostęp jako root?
ryekayo
0

Jeśli przechowywanie pełnego wyjścia docker savenie jest opcją, możesz użyć potoków, aby wyodrębnić z niego tylko potrzebny plik.

Niestety, ponieważ wynikiem jest „smoła smół”, może to być proces iteracyjny.

To, co zrobiłem, gdy potrzebowałem teraz wyodrębnić plik, to:

1) Określ, którą wersję obrazu ostatnio zmienił interesujący Cię plik (sposób, w jaki to robisz, prawdopodobnie zależy od Twojego obrazu) oraz datę jego utworzenia / zapisania

2) Uzyskaj pełny spis treści z danych wyjściowych docker savepolecenia za pomocą:

docker save IMAGE_NAME | tar -tvf -

3) Wyczyść layer.tarplik (i) na wyjściu tego polecenia, które pasują do daty obrazu określonego w kroku 1. (możesz dodać, | grep layer.taraby po prostu pokazać te pliki)

4) Wyodrębnij ten layer.tarplik do standardu i uzyskaj spis treści:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -tvf -

5) Sprawdź, czy żądany plik znajduje się na liście, i wypakuj go, gdy znajdziesz nazwę:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -xf - PATH/TO/YOUR/FILE

Jeśli istnieje więcej niż jeden layer.tarplik pasujący do daty, której szukasz w kroku 2/3, może być konieczne powtórzenie kroku 4 dla każdego z nich, aż znajdziesz właściwy

Zamień tekst drukowanymi literami w powyższych poleceniach na prawidłowe nazwy obrazów, sumy kontrolne i nazwy plików dla twojej sprawy.

Michael Firth
źródło