Я пытаюсь создать относительно простую установку для разработки и тестирования пакетов npm. Проблема заключалась в том, что после монтирования тома кода в контейнер он заменяет node_modules.
Я испробовал множество в целом логических вещей, в основном направленных на перемещение node_modules в другое место, а затем на ссылку в файлах конфигурации. Это работает, но решение уродливое. Кроме того, не рекомендуется устанавливать веб-пакет глобально, но мое решение требует этого.
Однако спустя какое-то время я нашел это решение, которое выглядит элегантно, как раз то, что мне было нужно, но и у него есть одна проблема. Я не совсем понимаю, как это работает.
Это моя версия того, как все работает.
Docker переупорядочивает монтирование томов на основе путей к контейнерам
Docker сначала монтирует подкаталог
Docker монтирует том родительского каталога, но из-за необъяснимого механизма он не переопределяет том подкаталога...
???
ВЫГОДА. Директория node_modules на месте, и веб-пакет работает отлично.
Итак, я действительно хочу понять, как на самом деле работает вся эта черная магия. Потому что без этих знаний я чувствую, что упускаю что-то важное.
Итак, ребята, как это работает?
Заранее спасибо.
services:
react-generic-form:
image: react-generic-form:package
container_name: react-generic-form-package
build:
dockerfile: dev.Dockerfile
context: ./package
volumes:
- "./package:/package"
- "/package/node_modules"
Это просто мое логическое предположение. Эта конфигурация предотвращает удаление каталога node_modules в контейнере при монтировании родительского каталога (/package). Единственный способ сделать это — смонтировать том подпапки, который является node_modules, перед его родителем. Поэтому я думаю, что перед монтированием томов с такой конфигурацией докер сначала переупорядочивает их по их пути и монтирует подкаталоги перед их родительскими каталогами.


Демон Docker при создании контейнера сортирует все точки монтирования, чтобы избежать затенения. (В не-Windows это происходит в (*github.com/docker/docker/daemon.Daemon).setupMounts.) Итак, в вашем примере:
/package, и /package/node_modules содержат данные, хранящиеся за пределами файлового пространства контейнера./package как привязка к именованному каталогу хоста. (Во-первых, потому что это более короткий путь.)/package/node_modules, затеняя эквивалентный каталог в предыдущем монтировании, вероятно, как привязку к каталогу с длинным шестнадцатеричным именем где-то в /var/lib/docker/volumes.Вы можете поэкспериментировать с этим с файлом docker-compose.yml, например
version: '3'
services:
touch:
image: busybox
volumes:
- ./b:/a/b
- ./a:/a
command: touch /a/b/c
Обратите внимание, что в каком бы порядке вы ни разместили volumes:, вы получите пустой каталог ./a/b (который становится точкой монтирования внутри контейнера) плюс пустой файл ./b/c (результат команды touch).
Также обратите внимание на заявление здесь о том, что каталог node_modules содержит данные, которые должны сохраняться при вызовах контейнера, и имеет жизненный цикл отдельно от контейнера или его базового образа. Изменение изображения и повторный запуск docker-compose up не повлияют на содержимое этого тома.
Вы правы, но проблема все еще здесь. Если мы смонтируем папку с хоста, который не содержит node_modules, это приведет к отсутствию node_modules в контейнере, потому что он должен переопределять содержимое папки контейнера, но не объединять его. Комментарий в коде говорит о том, что правильно, что правильно, когда вы монтируете что-то с хоста, но здесь node_modules не существует на хосте. node_modules существует в контейнере как слой изображения. Я попытался смонтировать только папку пакета, и он работает, как и ожидалось, node_modules стирается, а контейнер рушится. Итак, как объем node_modules предотвращает это?
Это фича или баг в Docker? Я просто не знаю. Кроме того, я думаю, что нашел короткое решение, которое будет работать нормально и будет логичным, но добавление одной строки в конфигурацию компоновки намного элегантнее.
Таким образом, в основном на любом другом языке обычной лучшей практикой для Docker является COPY код приложения в изображение; моей личной рекомендацией здесь было бы вообще не использовать тома.
Простое указание пути в volumes: сообщает Docker о создании анонимного тома, если это является источником вашей путаницы.
Мне нужно настроить dev env, поэтому тома — единственный способ заставить все работать, без них нет возможности сделать автокомпиляцию с просмотром файлов. В prod env все достаточно просто, код обновляется только слоем. Мне просто любопытно, потому что если я удалю анонимный том node_modules, все сломается, потому что вся папка контейнера заменяется папкой хоста, которая не содержит node_modules, а затем сборка завершается неудачно. Вопрос простой. Если том родительской папки монтируется первым, как том анонимной подпапки может предотвратить удаление подпапки контейнеров?
Где вы находите заявление о порядке
volumes:применяется?