Извлечь файл из образа докера?

24

Я хотел бы извлечь файл из образа Docker без необходимости запуска образа.

Эта docker saveопция в настоящее время не является жизнеспособной для меня, поскольку она сохраняет слишком большой файл только для того, чтобы распаковать конкретный файл.

BlakBat
источник
Какой дистрибутив вы используете?
Рекайо
@ryekayo: Ubuntu 14, докер 1.12.4 (API 1.24)
BlakBat

Ответы:

21

Вы можете извлечь файлы из изображения с помощью следующих команд:

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

Согласно docker create документации , контейнер не запускается:

Команда docker createсоздает доступный для записи слой-контейнер над указанным изображением и подготавливает его для выполнения указанной команды. Идентификатор контейнера затем печатается в STDOUT. Это похоже на то, docker run -dчто контейнер никогда не запускается. Затем вы можете использовать docker start <container_id>команду для запуска контейнера в любой точке.


Для справки (мой предыдущий ответ), менее эффективный способ извлечения файла из изображения следующий:

docker run some_image cat $file_path > $output_path
Би-би-
источник
3
Возможно, вы захотите переехать точку входа. docker run --entrypoint /bin/sh my_image -c /bin/cat some_file
Андрей
1
Это запускает изображение, что я и не хотел делать, как указано в моем вопросе.
BlakBat
Ах, это хороший момент. Я согласен, что мой текущий ответ не является удовлетворительным тогда.
Би - би -
1
@BlakBat Этот обновленный ответ работает для вас? Я думаю, что я должен был создать новый ответ, но это сделано сейчас.
Би-би-си
1
@bbc Этот обновленный ответ фактически не запускает контейнер (суть вопроса) и не требует наличия root.
BlakBat
2

Ничто из вышеперечисленного не помогло мне. Полная рабочая команда:

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

Без кавычек catпередается без имени файла, поэтому он не знает, что показать. Также рекомендуется удалить контейнер после завершения команды.

sekrett
источник
Команда, на которую вы ссылаетесь, будет работать только в зависимости от докера и от того, насколько правильно был задан ENTRYPOINT / CMD в Dockerfile; это не имеет ничего общего с цитированием. Вы также говорите, чтобы удалить контейнер, но вы указываете --rm. Наконец, когда я разместил свой вопрос, я указал «без запуска изображения», и ни один из ответов не был решением, учитывающим это.
BlakBat
1
Независимо от того, какие CMD и ENTRYPOINT были установлены в Dockerfile, я переопределяю оба, поэтому он будет работать всегда (в Linux, конечно). Что вы подразумеваете под "в зависимости от докера"? Настройки, версия, env, что? Ваш вопрос не является правильным, потому что изображения не могут быть выполнены, могут только контейнеры. Я думаю, что нет правильного ответа, вы должны иметь дело со многими файлами или создать временный контейнер. --rm удаляет временный контейнер, ответы других оставляют мусор на вашем диске.
Секрет
1

Если я не ошибаюсь, я считаю, что Docker-контейнеры хранят кэшированные файлы, созданные в следующей директории для Ubuntu:

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

Оттуда вы сможете получить доступ к файловой системе и получить ваши файлы.

ryekayo
источник
Нет. Этот каталог содержит только layersizeи json, и также не читается пользователем (даже если пользователь находится в группе Docker). /var/lib/docker/aufs/diffбудет содержать файл, который я ищу (но классифицируется не по идентификатору контейнера) и также не читается.
BlakBat
Дай мне немного, и я посмотрю. Я точно знаю, что есть способ получить файлы, не входя в контейнер и не запуская его.
ryekayo
Не читается, как это показывает? Я нашел пример, где вы можете извлечь текстовые файлы из контейнеров, перейдя в каталог / var / lib / docker / aufs / diff / *
ryekayo
Моя ошибка. Пользователь может получить доступ /var/lib/docker/aufs(но не ко всем другим каталогам /var/lib/docker/)
BlakBat
Можете ли вы получить доступ как root?
ryekayo
0

Если сохранение полного вывода docker saveне является вариантом, вы можете использовать конвейеры, чтобы извлечь из него только необходимый файл.

К сожалению, поскольку вывод представляет собой «tar of tars», это может быть слегка итеративный процесс.

Когда мне нужно было извлечь файл, я сделал следующее:

1) Определите, какую версию изображения интересующий вас файл изменил в последнее время (как вы это делаете, вероятно, зависит от вашего изображения), а также дату, когда он был создан / сохранен

2) Получить полное оглавление из вывода docker saveкоманды с помощью:

docker save IMAGE_NAME | tar -tvf -

3) Уточните layer.tarфайл (ы) в выходных данных этой команды, которые соответствуют дате изображения, которое вы определили на шаге 1. (Вы можете добавить, | grep layer.tarчтобы просто показать эти файлы)

4) Извлеките этот layer.tarфайл в стандартный формат и получите его содержание:

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

5) Убедитесь, что нужный файл указан в списке, и извлеките его, как только найдете имя:

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

Если существует несколько layer.tarфайлов, соответствующих дате, которую вы ищете на шаге 2/3, вам может потребоваться повторить шаг 4 для каждого из них, пока вы не найдете правильный

Замените текст заглавными буквами в приведенных выше командах на правильные имена изображений, контрольные суммы и имена файлов для вашего случая.

Майкл Ферт
источник