Как включить файлы из контекста сборки Docker, используя команду «ADD» в файле Docker?
Из документации Docker:
Путь должен быть внутри контекста сборки; Вы не можете ДОБАВИТЬ ../something/something, потому что первый шаг сборки докера - это отправить каталог контекста (и подкаталоги) демону докера.
Я не хочу реструктурировать весь свой проект, чтобы приспособить Docker к этому вопросу. Я хочу сохранить все мои файлы Docker в одном подкаталоге.
Кроме того, похоже, что Docker еще не поддерживает (и может не поддерживать) символические ссылки : команда Dockerfile ADD не следует по символическим ссылкам на хосте # 1676.
Единственное, о чем я могу подумать, это включить шаг перед сборкой, чтобы скопировать файлы в контекст сборки Docker (и настроить контроль версий для игнорирования этих файлов). Есть ли лучший обходной путь для этого?
FROM
для продолжения. Я бы не стал менять структуру проекта, чтобы приспособить ее к Docker (или к каким-либо инструментам сборки).Ответы:
Лучший способ обойти это - указать Dockerfile независимо от контекста сборки, используя -f.
Например, эта команда предоставит команде ADD доступ ко всему вашему текущему каталогу.
Обновление : Docker теперь позволяет иметь Dockerfile вне контекста сборки (исправлено в 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Так что вы также можете сделать что-то вроде
источник
dockerfile:
свойство вbuild:
разделе в файле Compose docs.docker.com/compose/compose-file/#/compose-file-referenceADD
получить файл, находящийся вне каталога контекста? Это то, что я пытаюсь сделать, но я не думаю, что использование-f
делает внешние файлы добавляемыми.build: context: .., dockerfile: dir/Dockerfile
. Теперь мой контекст сборки - это родительский каталог!Я часто использую эту
--build-arg
опцию для этой цели. Например, после добавления следующего в Dockerfile:Вы можете просто сделать:
Но обратите внимание на следующее предупреждение из документации Docker :
Предупреждение: не рекомендуется использовать переменные времени сборки для передачи таких секретов, как ключи github, учетные данные пользователя и т. Д. Значения переменных времени сборки видны любому пользователю образа с помощью команды истории докера.
источник
В Linux вы можете смонтировать другие каталоги вместо ссылки на них
См. Https://superuser.com/questions/842642 для получения более подробной информации.
Я не знаю, доступно ли что-то подобное для других ОС. Я также попытался использовать Samba для совместного использования папки и перемонтирования ее в контекст Docker, который также работал.
источник
Я провел хорошее время, пытаясь выяснить хороший шаблон и как лучше объяснить, что происходит с поддержкой этой функции. Я понял, что лучший способ объяснить это было следующим ...
Итак, с учетом сказанного, вот пример Dockerfile, который должен повторно использовать файл с именем
start.sh
Dockerfile
Он
ALWAYS
будет загружаться с относительного пути, имея текущий каталог dir в качествеlocal
ссылки на указанные вами пути.файлы
Учитывая эту идею, мы можем подумать о том, чтобы иметь несколько копий для файлов Docker, создающих определенные вещи, но им всем нужен доступ к
start.sh
.Учитывая эту структуру и файлы выше, вот docker-compose.yml
докер-compose.yaml
shared
контекст dir - этоruntime
dir.context
.dockerfile
.docker-compose.yml
Выглядит следующим образомall-service
устанавливается в качестве контекста, общий файлstart.sh
копируется туда, а также Dockerfile, указанный каждымdockerfile
.Ура!
источник
a/b/c
, то да, входdocker build .
в системуc
не позволит вам получить доступ../file-in-b
. Но я думаю, что общее недоразумение в этом (или, по крайней мере, в моем) было то, что контекст определяется местоположением, указанным в первом аргументе команды сборки, а не местоположением файла Dockerfile. Итак, как указано в принятом ответе: froma
:docker build -f a/b/c/Dockerfile .
означает, что в Dockerfile.
теперь находится папкаa
Если вы прочитаете обсуждение в выпуске 2745, не только Docker может никогда не поддерживать символические ссылки, но и может не поддерживать добавление файлов вне вашего контекста. Похоже, это философия дизайна, согласно которой файлы, которые входят в сборку Docker, должны быть явным образом частью его контекста или должны быть из URL, где он, по-видимому, также развернут с фиксированной версией, чтобы сборка повторялась с хорошо известными URL или файлами, поставляемыми с Докер контейнер.
Просто мое мнение, но я думаю, что вы должны реструктурировать, чтобы отделить код и Docker репозитории. Таким образом, контейнеры могут быть универсальными и загружать любую версию кода во время выполнения, а не во время сборки.
В качестве альтернативы используйте docker в качестве основного артефакта развертывания кода, а затем поместите файл docker в корень хранилища кода. Если вы идете по этому пути, то, вероятно, имеет смысл иметь родительский док-контейнер для более общих деталей системного уровня и дочерний контейнер для настройки, специфичной для вашего кода.
источник
Я считаю, что более простой обходной путь - изменить сам «контекст».
Так, например, вместо того, чтобы давать:
который устанавливает текущий каталог в качестве контекста, скажем, вы хотите, чтобы родительский каталог был контекстом, просто используйте:
источник
make build
и он вытягивает все файлы, необходимые, если они были обновлены, а затем вызывает соответствующую сборку докера ... Мне нужно проделать дополнительную работу, но она работает без нареканий, потому что я полностью контролирую ситуацию.Вы также можете создать архив того, что нужно изображению, и использовать его в качестве контекста.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
источник
tar zc /dir1 /dir2 |docker build -
. Это было очень полезно в моем случае.Используя docker-compose, я выполнил это, создав службу, которая монтирует нужные мне тома и фиксируя образ контейнера. Затем в последующем сервисе я полагаюсь на ранее зафиксированный образ, в котором все данные хранятся в смонтированных местах. Затем вам придется скопировать эти файлы в их конечный пункт назначения, так как смонтированные на хосте каталоги не фиксируются при выполнении
docker commit
командыисточник
У меня была такая же проблема с проектом и некоторыми файлами данных, которые я не смог переместить в контекст репо по причинам HIPPA. В итоге я использовал 2 Dockerfiles. Один создает основное приложение без необходимых мне материалов вне контейнера и публикует их во внутреннем репо. Затем второй файл Docker извлекает это изображение, добавляет данные и создает новое изображение, которое затем развертывается и нигде не сохраняется. Не идеально, но это помогло мне сохранить конфиденциальную информацию в хранилище.
источник
Простой обходной путь может заключаться в том, чтобы просто смонтировать том (используя флаг -v или --mount) в контейнер при его запуске и получить доступ к файлам таким образом.
пример:
для получения дополнительной информации см .: https://docs.docker.com/storage/volumes/
источник
docker run
слишком поздно.Как описано в этом выпуске GitHub, сборка фактически происходит
/tmp/docker-12345
, поэтому относительный путь like../relative-add/some-file
является относительным/tmp/docker-12345
. Таким образом, он будет искать/tmp/relative-add/some-file
, что также показано в сообщении об ошибке. *Не разрешается включать файлы из-за пределов сборочного каталога, поэтому это приводит к сообщению «Запрещенный путь». "
источник
Один быстрый и грязный способ - настроить контекст сборки на столько уровней, сколько вам нужно, но это может иметь последствия. Если вы работаете в архитектуре микросервисов, которая выглядит следующим образом:
Вы можете установить контекст сборки в родительский
Code
каталог, а затем получить доступ ко всему, но оказывается, что при большом количестве репозиториев это может привести к тому, что сборка займет много времени.Примером ситуации может быть то, что другая команда поддерживает схему базы данных,
Repo1
и код вашей командыRepo2
зависит от этого. Вы хотите связать эту зависимость с некоторыми вашими исходными данными, не беспокоясь об изменениях схемы или загрязняя хранилище другой группы (в зависимости от того, какие изменения вам, возможно, все же придется изменить в своих сценариях исходных данных) Конечно, второй подход - хакерский, но обходит проблему длинных сборок:Создайте скрипт sh (или ps1),
./Code/Repo2
чтобы скопировать нужные вам файлы и вызвать нужные вам команды docker, например:В файле docker-compose просто установите контекст как
Repo2
root и используйте содержимое./db/schema
каталога в вашем файле docker, не беспокоясь о пути. Имейте в виду, что вы рискуете случайно передать этот каталог в систему контроля версий, но действия по очистке сценариев должны быть достаточно простыми.источник
В моем случае мой Dockerfile написан как шаблон, содержащий заполнители, которые я заменяю реальными значениями, используя мой файл конфигурации.
Так что я не мог указать этот файл напрямую, но направить его в сборку Docker следующим образом:
Но из-за трубы
COPY
команда не сработала. Но вышеуказанный способ решает это путем-f -
(явно говоря, файл не предоставлен). Делая только-
без-f
флага, контекст И Dockerfile не предоставляются, что является предупреждением.источник
Хитрость заключается в том, чтобы понять, что вы можете указать контекст в команде сборки, чтобы включить файлы из родительского каталога, если вы укажете путь Docker, я бы изменил свой Dockerfile, чтобы он выглядел так:
Тогда моя команда сборки может выглядеть так:
Из каталога проекта
Из проекта / докера
источник