Оригинальный вопрос: Как использовать инструкцию VOLUME в Dockerfile?
Реальный вопрос , который я хочу , чтобы решить это - как монтировать тома хоста в докеров контейнеры в Dockerfile во время сборки, то есть, имея docker run -v /export:/export
возможность в течение docker build
.
Причина этого для меня заключается в том, что при создании объектов в Docker я не хочу, чтобы эти apt-get install
кэши ( ) блокировались в одном докере, а делился / использовал их повторно. Это основная причина, по которой я спрашиваю об этом вопросе.
Последнее обновление:
До docker v18.09 правильный ответ должен быть таким, который начинается с:
Существует способ монтировать том во время сборки, но он не включает Dockerfiles.
Однако это был плохо сформулированный, организованный и подтвержденный ответ. Когда я переустанавливал свой докер, я наткнулся на следующую статью:
Подключите сервис apt-cacher-ng к
https://docs.docker.com/engine/examples/apt-cacher-ng/.
Это решение докера на этот / мой вопрос, не прямо, а косвенно. Это обычный путь, который нам предлагает делать докер. И я признаю, что это лучше, чем тот, который я пытался спросить здесь.
Другой способ, недавно принятый ответ , например, Buildkit в v18.09.
Выберите тот, который подходит вам.
Был: было решение - рокер, который был не от Docker, но теперь, когда рокер снят с производства, я снова возвращаю ответ на «Невозможно» .
Старое обновление: так что ответ "Не возможно". Я могу принять его как ответ, так как знаю, что этот вопрос широко обсуждался на https://github.com/docker/docker/issues/3156 . Я могу понять, что переносимость является первостепенной проблемой для разработчика докеров; но как пользователь докера, я должен сказать, что очень разочарован этой отсутствующей функцией. Позвольте мне завершить мой аргумент цитатой из вышеупомянутого обсуждения: « Я хотел бы использовать Gentoo в качестве базового изображения, но определенно не хочу, чтобы после создания изображения было более 1 ГБ данных дерева Portage в любом из слоев. может иметь несколько хороших компактных контейнеров, если бы не гигантское дерево портежей, которое должно появиться на изображении во время установки.«Да, я могу использовать wget или curl для загрузки всего, что мне нужно, но тот факт, что из соображений переносимости теперь я вынужден загружать> 1 ГБ дерева Portage каждый раз, когда я создаю базовый образ Gentoo, не эффективен и не удобен для пользователя. Более того, хранилище пакетов ВСЕГДА будет находиться в / usr / portage, поэтому ВСЕГДА ПОРТАТИВНО в Gentoo. Опять же, я уважаю это решение, но, пожалуйста, позвольте мне также выразить свое разочарование в то же время. Спасибо.
Оригинальный вопрос в деталях:
Из
Поделиться каталогами через тома
http://docker.readthedocs.org/en/v0.7.3/use/working_with_volumes/
в нем говорится, что функция томов данных «была доступна с версии 1 Docker Remote API». Мой докер версии 1.2.0, но я обнаружил, что приведенный выше пример не работает:
# BUILD-USING: docker build -t data .
# RUN-USING: docker run -name DATA data
FROM busybox
VOLUME ["/var/volume1", "/var/volume2"]
CMD ["/usr/bin/true"]
Как правильно в Dockerfile монтировать тома, установленные на хосте, в контейнеры Docker с помощью команды VOLUME?
$ apt-cache policy lxc-docker
lxc-docker:
Installed: 1.2.0
Candidate: 1.2.0
Version table:
*** 1.2.0 0
500 https://get.docker.io/ubuntu/ docker/main amd64 Packages
100 /var/lib/dpkg/status
$ cat Dockerfile
FROM debian:sid
VOLUME ["/export"]
RUN ls -l /export
CMD ls -l /export
$ docker build -t data .
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM debian:sid
---> 77e97a48ce6a
Step 1 : VOLUME ["/export"]
---> Using cache
---> 59b69b65a074
Step 2 : RUN ls -l /export
---> Running in df43c78d74be
total 0
---> 9d29a6eb263f
Removing intermediate container df43c78d74be
Step 3 : CMD ls -l /export
---> Running in 8e4916d3e390
---> d6e7e1c52551
Removing intermediate container 8e4916d3e390
Successfully built d6e7e1c52551
$ docker run data
total 0
$ ls -l /export | wc
20 162 1131
$ docker -v
Docker version 1.2.0, build fa7b24f
VOLUME ~/host_dir ~/container_dir
. Дискуссия довольно обширная, если кратко изложить, в чем причина?Ответы:
Во-первых, чтобы ответить "почему не
VOLUME
работает?" Когда вы определяетеVOLUME
в Dockerfile, вы можете определить только цель, а не источник тома. Во время сборки вы получите только анонимный том от этого. Этот анонимный том будет подключаться к каждойRUN
команде, предварительно заполняться содержимым изображения и затем удаляться в концеRUN
команды. Сохраняются только изменения в контейнере, а не изменения в объеме.Поскольку этот вопрос был задан, было выпущено несколько функций, которые могут помочь. Во-первых, это многоэтапные сборки, позволяющие вам создать неэффективное первое место на диске и скопировать только необходимые выходные данные на последний этап, который вы отправляете. И вторая особенность - это Buildkit, которая кардинально меняет способ создания образов и добавления новых возможностей в сборку.
Для многоэтапной сборки у вас должно быть несколько
FROM
строк, каждая из которых начинает создание отдельного изображения. Только последнее изображение помечено по умолчанию, но вы можете копировать файлы с предыдущих этапов. Стандартное использование состоит в том, чтобы иметь среду компилятора для создания бинарного или другого артефакта приложения и среду выполнения в качестве второго этапа копирования этого артефакта. Вы могли бы иметь:Это приведет к сборке, которая содержит только результирующий двоичный файл, а не каталог full / export.
Buildkit выходит из экспериментального в 18.09. Это полная переработка процесса сборки, включая возможность изменения синтаксического анализатора внешнего интерфейса. В одном из этих изменений парсера реализована
RUN --mount
опция, которая позволяет вам смонтировать каталог кэша для ваших команд запуска. Например, вот тот, который монтирует некоторые каталоги debian (с переконфигурированием образа debian это может ускорить переустановку пакетов):Вы должны настроить каталог кэша для любого кэша приложения, например, $ HOME / .m2 для maven или /root/.cache для golang.
TL; DR: Ответ здесь: с этим
RUN --mount
синтаксисом вы также можете связать каталоги монтирования только для чтения из контекста сборки. Папка должна существовать в контексте сборки, и она не отображается обратно на хост или клиент сборки:Обратите внимание: поскольку каталог монтируется из контекста, он также монтируется только для чтения, и вы не можете отправить изменения обратно на хост или клиент. При сборке вы захотите установить версию 18.09 или новее и включить buildkit с помощью
export DOCKER_BUILDKIT=1
.Если вы получаете сообщение об ошибке, что флаг монтирования не поддерживается, это означает, что вы либо не включили buildkit с помощью указанной выше переменной, либо что ранее вы не включали экспериментальный синтаксис со строкой синтаксиса в верхней части Dockerfile. любые другие строки, включая комментарии. Обратите внимание, что переменная для переключения buildkit будет работать только в том случае, если в вашей установке Docker встроена поддержка buildkit, для которой требуется версия 18.09 или новее из Docker, как на клиенте, так и на сервере.
источник
Невозможно использовать
VOLUME
инструкцию, чтобы указать докеру, что монтировать. Это серьезно нарушило бы мобильность. Эта инструкция сообщает докеру, что содержимое этих каталогов не входит в изображения и может быть доступно из других контейнеров с помощью параметра--volumes-from
командной строки. Вы должны запустить контейнер, используя-v /path/on/host:/path/in/container
для доступа к каталогам с хоста.Монтирование томов хоста во время сборки невозможно. Нет привилегированной сборки, и установка хоста также может серьезно ухудшить переносимость. Возможно, вы захотите попробовать использовать wget или curl, чтобы загрузить все необходимое для сборки и поставить его на место.
источник
ОБНОВЛЕНИЕ: Кто-то просто не примет ответ как «нет», и мне это очень нравится, особенно на этот конкретный вопрос.
Хорошие новости, есть способ -
Решение Rocker: https://github.com/grammarly/rocker
Джон Яни сказал : «ИМО, он решает все слабые места Dockerfile, делая его пригодным для разработки».
коромысло
https://github.com/grammarly/rocker
Обновление: Rocker был прекращен, согласно официальному репо проекта на Github
источник
MOUNT ~/code/docker-app-dev/new-editor/:/src/
а моя команда сборки Rocker - такаяrocker build -f Dockerfile .
. Что я делаю не так?~
метасимвол оболочки БорнаRocker build
не разрешает параметрыdocker run
командной строки, поэтому в настоящее время не разрешает такие вещи, как--privileged
.Существует способ монтировать том во время сборки, но он не включает Dockerfiles.
Техника будет состоять в том, чтобы создать контейнер из любой базы, которую вы хотите использовать (смонтировать ваш том (ы) в контейнере с
-v
опцией), запустить скрипт оболочки, чтобы выполнить работу по созданию вашего изображения, а затем зафиксировать контейнер как изображение, когда закончите. ,Это не только исключит лишние файлы, которые вам не нужны (это также хорошо для защищенных файлов, таких как файлы SSH), но также создаст одно изображение. У этого есть недостатки: команда commit не поддерживает все инструкции Dockerfile, и она не позволяет вам забрать, когда вы остановились, если вам нужно отредактировать ваш скрипт сборки.
ОБНОВИТЬ:
Например,
источник
debian:wheezy
и сценарий оболочкиbuild.sh
, какие конкретные инструкции будут использовать?Когда вы запускаете контейнер, каталог на вашем хосте создается и монтируется в контейнер. Вы можете узнать, с каким каталогом это
Если вы хотите смонтировать каталог со своего хоста внутри контейнера, вы должны использовать
-v
параметр и указать каталог. В вашем случае это будет:Так что вы бы использовали папку hosts внутри вашего контейнера.
источник
Я думаю, что вы можете сделать то, что вы хотите, запустив сборку с помощью команды docker, которая сама запускается внутри контейнера docker. См. Docker теперь может работать в Docker | Блог Докера . Была использована такая техника, но которая на самом деле осуществляла доступ к внешнему докеру с помощью контейнера, например, при изучении того, как создать наименьший возможный контейнер Docker | Блог Ксебии .
Еще одна важная статья - Оптимизация изображений Docker | CenturyLink Labs , в которой объясняется, что, если вы в конечном итоге загружаете материал во время сборки, вы можете избежать потери пространства им в конечном изображении, загружая, создавая и удаляя загрузку, все за один шаг RUN.
источник
Это некрасиво, но я достиг подобия этого примерно так:
Dockerfile:
imageBuild.sh:
У меня есть Java-сборка, которая загружает юниверс в /root/.m2, и делал это каждый раз .
imageBuild.sh
копирует содержимое этой папки на хост после сборки иDockerfile
копирует их обратно в образ для следующей сборки.Это что-то вроде того, как будет работать том (т.е. он сохраняется между сборками).
источник
Вот упрощенная версия двухэтапного подхода с использованием build и commit без сценариев оболочки. Это включает в себя:
С относительно небольшими изменениями дополнительный шаг добавляет всего несколько секунд ко времени сборки.
В принципе:
В моем случае я хочу предварительно сгенерировать файл maven toolchains.xml, но многие мои установки JDK находятся на томе, который недоступен до времени выполнения. Некоторые из моих изображений несовместимы со всеми JDKS, поэтому мне нужно проверить совместимость во время сборки и условно заполнить toolchains.xml. Обратите внимание, что мне не нужно, чтобы изображение было переносимым, я не публикую его в Docker Hub.
источник
Как уже отвечали многие, монтировать тома хоста во время сборки невозможно. Я просто хотел бы добавить
docker-compose
способ, я думаю, что это будет хорошо, в основном для разработки / тестированияDockerfile
докер-compose.yml
И запустить свой контейнер
docker-compose up -d --build
источник