Как скопировать файл из контейнера docker
Обновлено: 07.07.2024
В идеальном случае передача изображений Docker осуществляется через реестр Docker или через полностью управляемого поставщика, такого как AWS ECR или Google GCR. Вы можете легко загрузить изображение с помощью команды docker push , а другие могут получить изображение с помощью команды docker pull .
Хотя, если вам нужно переместить изображение с одного хоста на другой, чтобы протестировать его перед отправкой в производственную среду, или вы хотите поделиться этим изображением с кем-то в офисе, это можно сделать, экспортировав изображение как .tar файл.
Docker поддерживает два разных типа методов для сохранения изображений контейнера в один архив.
- Docker save - Save используется для сохранения изображения (не контейнера)
- Docker export - Export используется для сохранения контейнера (не изображения)
Использование Docker Save Command:
Сохранение изображения Docker:
Во-первых, мы будем придерживаться плана, который сохраняет только изображение. Теперь пройдемся по команде docker save . Предположим, вам нужен образ Python с Alpine, который можно извлечь из Docker Hub:
После добавления нескольких файлов или внесения изменений в контейнер вы решаете создать архив изображения, чтобы предоставить его коллеге. Вы можете достичь этого, выполнив следующую команду:
Просто убедитесь, что вы используете точное имя изображения и тег при создании tar. В нашем случае так и было python:2.7.17-alpine3.9 . Вы можете проверить, сработала ли вышеуказанная команда:
Загрузка изображения докера:
Как только на целевой машине будет файл .tar , вы можете загрузить образ в локальный реестр, используя команду docker load :
Теперь проверьте, есть ли у вас это изображение на целевом компьютере, с помощью docker images или docker image list . Конечный результат будет примерно таким:
Использование команды экспорта Docker:
Примечание. Команда docker export не будет экспортировать содержимое тома, который прикреплен к контейнеру. В этом случае вам необходимо выполнить дополнительную команду для резервного копирования, восстановления или миграции существующего тома.
Посмотрев на метод docker export , сначала мы потянем альпийское изображение:
Теперь вы можете запустить экземпляр в режиме отсоединения, чтобы контейнер не разрушался при выходе из него.
Чтобы получить идентификатор контейнера и имя, которое мы создали, мы можем использовать команду docker ps . На всякий случай, если на вашей машине контейнер был остановлен по какой-либо причине, вы все равно можете получить идентификатор и имя, используя docker ps -a :
Как мы видим, наш идентификатор контейнера 35f34fabfa84 (он будет другим для вас), или вы также можете использовать имя контейнера; в нашем случае это alpine-t . Теперь мы можем запустить команду docker export для экспорта изображения экземпляра:
Кроме того, вы также можете использовать OPTIONS, чтобы сделать то же самое, и ваш файл .tar будет готов для передачи.
Теперь вы можете импортировать файл .tar на целевой компьютер, используя импорт докера:
Чтобы проверить, вы можете запустить контейнер с помощью --rm (он уничтожит контейнер, как только вы его выполните):
Я думаю об использовании Docker для построения моих зависимостей на сервере Continuous Integration (CI), чтобы мне не пришлось устанавливать все среды выполнения и библиотеки на самих агентах.
Для этого мне нужно скопировать артефакты сборки, которые встроены в контейнер, обратно в хост. Это возможно?
Чтобы скопировать файл из контейнера на хост, вы можете использовать команду
Здесь goofy_roentgen - это имя контейнера, которое я получил от следующей команды:
Вы также можете использовать (часть) ID контейнера . Следующая команда эквивалентна первой
Вот удобный способ получить в вашем последний контейнер , если вы просто используете докер для среды Linux темпа: docker ps -alq . Эта команда cp также работает как есть для копирования деревьев каталогов (не только одного файла). В новых версиях Docker вы можете копировать в двух направлениях (хост-контейнер или контейнер-хост) с помощью docker cp . Мне нужно docker cp -L было скопировать символические ссылки ПРИМЕЧАНИЕ: контейнер не должен быть запущен, чтобы использовать команду cp. Удобно, если ваш контейнер постоянно падает.Вам не нужно использовать docker run .
Вы можете сделать это с docker create .
Команда docker create создает доступный для записи слой контейнера над указанным изображением и подготавливает его для выполнения указанной команды. Идентификатор контейнера затем печатается в STDOUT . Это похоже на то, docker run -d что контейнер никогда не запускается.
Итак, вы можете сделать:
Здесь вы никогда не запускаете контейнер. Это выглядело выгодно для меня.
Это требует больше голосов. Отлично подходит для случаев, когда вам просто нужно создать что-то в контейнере, а затем скопировать результаты. @HonzaKalfus Я согласен, что это должно быть выше. Это именно то, что я был после. Я использовал это так, чтобы я мог создавать некоторые двоичные файлы, используя известную среду (amazon linux в определенной версии). смог создать сценарий оболочки, который полностью собрал докер и извлек из него полученный бинарный файл! Отлично. @jII, я сделал это, потому что позже я запускаю на нем докер. В простых случаях это не нужно, но и здесь не вредит. Можно ли как-то использовать подстановочные знаки? Я имею в виду . Я не знаю точное имя файла, который мне нужно скопировать, потому что на нем есть номер версии.Смонтируйте «том» и скопируйте туда артефакты:
Затем, когда сборка заканчивается, и контейнер больше не работает, он уже скопировал артефакты из сборки в artifacts каталог на хосте.
редактировать
Предостережение: при этом вы можете столкнуться с проблемами с идентификатором пользователя докера, совпадающим с идентификатором текущего запущенного пользователя. То есть файлы в /artifacts будут показаны как принадлежащие пользователю с UID пользователя, использованного внутри контейнера докера. Обходным путем может быть использование UID вызывающего пользователя:
На самом деле вы можете использовать chown команду для сопоставления идентификатора пользователя и идентификатора группы на хост-компьютере. Уже сделал, и это не сработает. После того как контейнер скопировал файлы на том в первый раз, в следующий раз том больше не будет пустым, и файлы не будут перезаписаны более новыми. Контейнер отдает приоритет файлам хоста (те, которые были скопированы при первом подключении образа контейнера). звучит как что-то, что может быть своим собственным вопросом @FrondorСмонтируйте том, скопируйте артефакты, настройте идентификатор владельца и идентификатор группы:
Описание
docker run с томом хоста, chown артефактом, cp артефактом для тома хоста:
Этот трюк работает, потому что chown вызов внутри heredoc принимает $(id -u):$(id -g) значения извне работающего контейнера; т.е. хост докера.
- Вы не должны docker container run --name или docker container create --name раньше
- вам не нужно docker container rm после
Если у вас нет работающего контейнера, только изображение, и если вы хотите скопировать только текстовый файл, вы можете сделать что-то вроде этого:
Я публикую это для всех, кто использует Docker для Mac. Вот что сработало для меня:
Обратите внимание, что при монтировании с использованием -v этого backup каталога автоматически создается.
Надеюсь, это кому-нибудь пригодится. :)
Если вы используете docker-compose, volume-from устарела в версии 3 и после.Если вы просто хотите извлечь файл из изображения (вместо работающего контейнера), вы можете сделать это:
docker run --rm <image> cat <source> > <local_dest>
Это вызовет контейнер, запишет новый файл, затем удалит контейнер. Однако один недостаток заключается в том, что права доступа к файлу и дата изменения не будут сохранены.
С выпуском Docker 19.03 вы можете пропустить создание контейнера и даже создание образа. Существует вариант с сборками на основе BuildKit для изменения выходного назначения. Вы можете использовать это для записи результатов сборки в локальный каталог, а не в изображение. Например, вот сборка go-файла:
Из приведенного выше Dockerfile я создаю artifact этап, который включает только файлы, которые я хочу экспортировать. И недавно введенный --output флаг позволяет мне записывать их в локальный каталог вместо изображения. Это необходимо выполнить с помощью движка BuildKit, который поставляется с 19.03:
Docker имеет две похожие инструкции Dockerfile, COPY и ADD, обе из которых используются для импорта файлов в образ. В этой статье объясняется, почему лучше использовать COPY вместо ADD, если вы не хотите автоматически извлекать локальный пакет tar в образ.
Рекомендации по использованию инструкции КОПИРОВАТЬ
Эта инструкция Dockerfile копирует один или несколько локальных файлов или папок в целевой образ докера.
- COPY <source>… <destination>
- COPY ["<источник>", . "<место назначения>"] (этот формат требуется для путей, содержащих пробелы)
Например, используйте инструкцию COPY в Dockerfile.
Это простой пример того, как использовать инструкцию COPY в Dockerfile для создания приложения Ruby.
Он строит изображение в слоях, начиная с родительского изображения ruby: 2.5.1, используя определение FROM.
Используйте инструкцию WORKDIR, чтобы определить рабочий каталог, а затем используйте инструкцию COPY или ADD.
В этом случае, когда используется копия, он будет копировать файл из локального источника. Указывает файл в текущем каталоге в месте, определенном WORKDIR. В приведенном выше примере вторая КОПИЯ означает, что рабочий каталог в зеркале копируется из текущего каталога.
Рекомендации по использованию КОПИРОВАНИЯ для создания зеркальных слоев
Docker рекомендует использовать COPY для создания слоев изображений, сохраняя разные контексты файлов в разных слоях изображений. Это означает, что реконструкция изображения эффективна. Файлы, которые, скорее всего, будут изменены, должны находиться на нижних уровнях, а файлы, которые, скорее всего, будут изменены, должны быть добавлены последними.
Если есть несколько шагов dockerfile с использованием контекстов из разных файлов, скопируйте их по отдельности, а не все сразу. Это гарантирует, что кеш сборки для каждого шага становится недействительным только при изменении особо необходимых файлов.
–Best practices for writing Dockerfiles
Этот принцип продемонстрирован в приведенном выше примере файла dockerfile. Скопировав Gemfiles, а затем выполнив Run bundle install, вы можете использовать установленные рубиновые драгоценные камни для создания слоя изображения, который можно кэшировать. Последние две инструкции докера копируют файлы приложения в образ и используют CMD для установки команд по умолчанию.
Это означает, что при изменении каких-либо файлов приложения образ Docker можно регенерировать, используя родительский и средний уровни кеша. Это намного эффективнее, чем создание всех этих моделей с нуля.
Почему не стоит использовать инструкцию ADD
Синтаксис инструкции ADD аналогичен синтаксису COPY. Помимо копирования локальных файлов и каталогов в место назначения в образе Docker, он также имеет некоторые дополнительные функции.
- ADD <source>… <destination>
- ДОБАВИТЬ ["<источник>", . "<место назначения>"] (Этот формат требуется для путей, содержащих пробелы)
Однако официальное руководство Dockerfile по лучшей практике указывает, что в большинстве случаев COPY является предпочтительной инструкцией по сравнению с ADD.
Хотя функции ДОБАВЛЕНИЯ и КОПИРОВАНИЯ схожи, в общем случае предпочтительнее КОПИРОВАТЬ. Это потому, что он более прозрачен, чем ADD. COPY поддерживает только копирование локальных файлов в контейнер, в то время как ADD имеет некоторые менее очевидные функции (такие как локальное извлечение tar и поддержка удаленных URL). Поэтому лучше всего использовать ADD для автоматического извлечения локального tar-файла на зеркало, например ADD rootfs.tar.xz /
-— Best practices for writing Dockerfiles
Еще одна дополнительная функция ADD - это то, что он может копировать файлы с URL-адресов, но Docker рекомендует не использовать его для этой цели.
Рекомендации по копированию файлов с URL
Если источником ADD является URL-адрес, он загрузит файл и скопирует его в место назначения в образе докера. Докер считает, что использование добавления для копирования с URL-адреса обычно неэффективно, и для включения необходимых удаленных файлов лучше использовать другие стратегии.
Поскольку размер изображения важен, настоятельно рекомендуется не использовать ADD для получения пакетов с удаленного URL-адреса; вам следует использовать curl или wget. Таким образом, вы можете удалить файлы, которые больше не нужны после извлечения, без добавления к изображению других слоев.
-— Dockerfile Best Practices
Например, следует избегать следующих действий:
Вместо этого выполните следующие операции:
Когда следует использовать инструкцию ADD
Если <source> является локальным tar-файлом в узнаваемом формате сжатия, он будет автоматически распакован в образ Docker как каталог. Например: добавьте rootfs.tar.xz /. Это сценарий ADD, официально рекомендованный докером.
Для других файлов или каталогов, для которых функция автоматической распаковки ADD не требуется, всегда следует использовать COPY.
Это третья часть серии статей про Docker и она всецело посвящена Docker-файлам. В первой части основные концепции Docker объясняются на простых примерах из жизни. Во второй статье — краткий обзор экосистемы Docker.
Docker-образы
Docker-образ создаётся во время сборки, а Docker-контейнер — во время запуска приложения.
Каждый Docker-образ содержит файл с именем Dockerfile (он без расширения). При вызове docker build предполагается, что Dockerfile будет находиться в текущей рабочей директории. Но с помощью флага -f можно указать другое расположение.
Руководитель направления (Technical Product Manager)Sportmaster Lab , Липецк, Санкт-Петербург, Москва , От 200 000 до 300 000 ₽
При загрузке Docker-образа из удалённого репозитория скачиваются только отсутствующие у вас слои. Docker экономит место и время, повторно используя уже существующие слои.
Инструкция Docker-файла — слово в верхнем регистре, которое стоит перед аргументом какой-либо команды. Каждая строка в Docker-файле может содержать инструкцию, все они обрабатываются сверху вниз. Инструкции выглядят так:
Эта статья предполагает использование Unix Docker-образа. Вы, конечно, можете использовать и Windows Docker-образ, но он медленнее, менее удобный и, вообще, его не часто применяют. Так что, пользуйтесь Unix по возможности.
Несколько Docker-инструкций
Инструкции и примеры к ним
Docker-файл чисто теоретически может содержать только одну строчку:
В этом примере хранилище образов — Ubuntu. Ubuntu — название официального Docker-репозитория, в котором и содержится данная ОС.
Заметьте, что этот Docker-файл содержит тег для базового образа: 18.04, который указывает Docker’у, какую именно версию образа нужно использовать. Если тег не указан, по умолчанию берётся последняя версия образа. Но лучше всё же указывать тег базового образа. Когда Docker-файл, приведённый выше, используется для создания локального Docker-образа впервые, он загружает слои, указанные в образе Ubuntu.
При создании Docker-контейнера, вы помещаете наверх слой, который впоследствии можно будет изменить.
Когда образ запущен, и нужно произвести некоторые изменения, файл копируется на верхний слой, доступный для редактирования. Узнать, как это делается, можно здесь.
Подробнее про Docker-файл
Кроме того, что ваш однострочный образ сжат, он ещё и медленный, предоставляет мало информации и ничего не делает во время запуска контейнера. Посмотрите на более длинный Docker-файл, который запускает более легковесный образ, а также выполняет скрипт во время запуска.
Но что же это всё обозначает?
В роли базового образа выступает официальный Python-образ с тегом 3.7.2-alpine3.8. Как вы можете увидеть из исходников, образ включает в себя Linux, Python и ничего более. Alpine-образы очень популярны, потому что они маленькие, быстрые и безопасные. Однако Alpine-образы не поставляются сразу со всеми компонентами, характерными для вашей ОС. Некоторые пакеты вам придётся установить самостоятельно.
LABEL
Следующая инструкция — LABEL . LABEL добавляет метаданные к образу, предоставляет контактную информацию. Она не замедляет процесс запуска и не занимает много места, наоборот, обеспечивает образ полезной информацией, так что обязательно используйте её. Больше про LABEL читайте здесь.
ENV создаёт переменную окружения, которая становится доступной во время запуска контейнера. В примере выше вы могли видеть использование переменной ADMIN при создании контейнера.
ENV удобна для обозначения констант. Если константа используется в нескольких местах файла Dockerfile, и вам понадобится изменить её значение позднее, это можно будет сделать в одном месте.
Docker-файл зачастую предоставляет несколько путей решения одной задачи. Будет хорошо, если в вашем решении будет учитываться баланс Docker-соглашений, прозрачность и скорость. К примеру, RUN , CMD и ENTRYPOINT служат различным целям и могут использоваться для выполнения команд.
RUN создаёт слой во время запуска. Docker фиксирует состояние образа после каждой инструкции RUN .
apk — это сокращение от Alpine Linux package manager. Если вы используете базовый образ не Alpine Linux, то установка пакетов производится командой RUN apt-get .
RUN и её родственные инструкции: CMD , ENTRYPOINT — могут быть как форме оболочки, так и в форме shell-скрипта. Во втором случае используют JSON-синтаксис: RUN ["my_executable", "my_first_param1", "my_second_param2"] . А в примере выше использовалась форма оболочки: RUN apk update && apk upgrade && apk add bash .
Позднее в вашем Docker-файле вы будете создавать новую директорию, используя ["mkdir", "/a_directory"] . Не забывайте, что в JSON нужно использовать двойные кавычки!
Инструкция COPY . ./app говорит Docker’у, что нужно скопировать файлы и папки из вашей локальной сборки в рабочую директорию образа. COPY создаст все нужные папки, если они отсутствуют.
ADD делает то же самое, что и COPY , но с двумя отличиями. ADD может загружать файлы по URL, а также извлекать локальные TAR-файлы.
В примере выше ADD копировала файлы по URL внутрь директории контейнера. Но официальныя документация не рекомендует использовать ADD так, потому что потом вы попросту не сможете удалить файлы. А дополнительные файлы увеличивают размер образа.
CMD — инструкция для запуска чего-либо во время запуска самого контейнера. По ходу сборки она не фиксирует никакого результата. В примере выше во время сборки запускался скрипт my_script.py .
Ещё пара моментов о CMD :
- Только одна CMD -инструкция на весь Docker-файл. Иначе все кроме последней будут проигнорированы;
- CMD может включать исполняемый файл;
- Если же CMD не содержит никакого файла, обязательно должна быть инструкция ENTRYPOINT . В этом случает обе инструкции должны быть в формате JSON;
- Аргументы командной строки для запуска Docker переопределяют аргументы, предоставленные CMD в Docker-файле.
Готовы к большему?
В следующем примере представлены ещё несколько Docker-инструкций:
Для Alpine Docker-образа вы используете apk. apk для типичной Linux-сборки — apt-get . Например, пакеты для базового Ubuntu-образа могут быть установлены и обновлены так: RUN apt-get update && apt-get install my_package .
В дополнение к apk и apt-get , Python-пакеты могут быть установлены через pip, wheel и conda. Методы варьируются в зависимости от языка.
Нижележащие слои должны предоставить свое средство установки и управления пакетами. Если возникнет проблема с установкой пакетов, убедитесь, что у вас установлен менеджер пакетов.
Можно использовать RUN вместе с pip и списком нужных пакетов. Для этого объедините команды установки пакетов в одну инструкцию и разделите их символом продолжения строки ( \ ). Этот метод позволяет улучшить читаемость и уменьшить количество слоев (из-за отсутствия возможности использовать несколько RUN инструкций).
Также вы можете запустить установщик, указав ему файл, содержащий все зависимости для вашего образа. Обычно он называется requirements.txt.
WORKDIR
Меняет текущую рабочую директорию в контейнере для инструкций: COPY , ADD , RUN и ENTRYPOINT .
- Предпочтительно задать абсолютный путь с помощью WORKDIR, а не перемещаться по файловой системе с помощью команд cd в Docker-файле;
- WORKDIR автоматически создаёт директорию, если её ещё нет;
- Можно использовать несколько WORKDIR -инструкций. Если используются относительные пути — каждая инструкция поменяет рабочую директорию.
Определяет переменную для передачи из командной строки в образ. Для ARG можно указать значение по умолчанию: ARG my_var=my_default_value .
В отличие от ENV -переменных, ARG -переменные не доступны для запущенных контейнеров. Однако вы можете использовать их для установки дефолтных значений для ENV -переменных, когда вы создаёте образ. И затем ENV-переменные сохраняются. Больше про это вы найдёте здесь.
ENTRYPOINT
ENTRYPOINT тоже позволяет вам задавать дефолтные команды и аргументы во время запуска контейнера. Она похожа на CMD , но параметры ENTRYPOINT не переопределяются, если контейнер запущен с параметрами командной строки.
Вместо этого аргументы командной строки, передаваемые docker run myimagename , добавляются к аргументам инструкции ENTRYPOINT . Например, docker run my_image bash добавляет аргумент bash в конец, ко всем другим аргументам ENTRYPOINT .
Docker-файл обязательно должен содержать либо CMD -инструкцию, либо ENTRYPOINT -инструкцию.
В официальной документации есть несколько советов, которые помогут сделать выбор между CMD и ENTRYPOINT для начальной команды:
- Если вам нужно запускать одну и туже команду несколько раз, выбирайте ENTRYPOINT ;
- Используйте ENTRYPOINT , когда ваш контейнер выступает в роли исполняющейся программы;
- При наличии дополнительных дефолтных аргументов, которые могут быть изменены через командную строку, лучше подойдёт CMD .
В примере выше, ENTRYPOINT ["python", "my_script.py", "my_var"] запускает в контейнере Python-скрипт my_script.py с аргументом my_var . Затем переменная my_var может быть использована в my_script argparse. Заметьте, у my_var есть дефолтное значение, ранее установленное в Docker-файле при помощи ARG . Так что, если аргумент не будет задан через командную строку, возьмётся его значение по умолчанию.
Как правило, Docker рекомендует вам использовать исполняемую форму с JSON-синтаксисом ENTRYPOINT ["executable", "param1", "param2"] .
EXPOSE
Инструкция EXPOSE показывает, какой порт пробрасывать из контейнера.
Используйте команду docker run с флагом -p для пробрасывания и сопоставления нескольких портов во время запуска. Флаг в верхнем регистре -P будет пробрасывать все открытые порты.
VOLUME
VOLUME определяет, где контейнер будет хранить постоянные данные и получать к ним доступ.
Заключение
В этой статье не были упомянуты такие инструкции, как USER , ONBUILD , STOPSIGNAL , SHELL , и HEALTHCHECK , информацию про них вы сможете найти здесь.
Читайте также: