Додати том до Docker, але виключити підпапку


209

Припустимо, у мене є контейнер Docker і папка на хості /hostFolder. Тепер, якщо я хочу додати цю папку в контейнер Docker як об'єм, я можу це зробити або використовуючи ADDв, Dockerfileабо монтуючи її як об'єм.

Все йде нормально.

Тепер /hostFolderмістить вкладену папку, /hostFolder/subFolder.

Я хочу вмонтуватись /hostFolderу контейнер Docker (чи не має значення читання-запис чи лише читання, працює для мене обох), але я НЕ хочу, щоб він включався /hostFolder/subFolder. Я хочу виключити це, і я також хочу, щоб контейнер Docker міг внести зміни в цю підпапку, без наслідків того, що вона також змінилася на хості.

Чи можливо це? Якщо так, то як?


2
@AbhijitSarkar це не дуже конструктивний (ні в якому разі не корисний) коментар.
кано

1
@Kano Це коментар, а не відповідь.
Abhijit Sarkar

Відповіді:


396

Використовуючи docker-compose, я можу використовувати node_modules локально, але ігнорувати його в контейнері docker, використовуючи наступний синтаксис у docker-compose.yml

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/

Отже, все в ./angularAppкарти відображається, /opt/appі тоді я створюю ще один том монтажу, /opt/app/node_modules/який зараз порожній каталог - навіть якщо в моїй локальній машині ./angularApp/node_modulesне порожньо.


3
Це працює, але я не можу видалити ці пачки всередині контейнера. Наприклад: мені потрібно замінити /opt/app/node_modules/інший каталог з такою ж назвою. Буває помилка: "гучно зайнятий"
Степан Юдін

32
Не забудьте останню косу рису! напр. / opt / app / node_modules не працює, він буде перезаписаний ./angularApp/node_modules
Stingus

3
Цей трюк працював для мене, але, здається, вже не для навіть самого файлу Compose. Цікаво, якби це також перестало працювати на інших.
plinehan

8
Дякую! Ти врятував мій день! У разі використання простого докера, а не композиції, це виглядатиме так: -v $(pwd):/build/ -v /build/node_modules
Богдан Март

3
Я знайшов документ, docs.docker.com/storage/volumes/… . If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume.
хіроші

118

Якщо ви хочете, щоб підкаталоги ігнорували docker-compose, але стійкі, ви можете зробити наступне в docker-compose.yml:

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules

Це зможе монтувати ваш поточний каталог як спільний том, але замість локального node_modulesкаталогу змонтувати стійкий том докера . Це схоже на відповідь @kernix, але це дозволить node_modulesзберігатись між docker-compose upзапусками, що, ймовірно, бажана поведінка.


20
Іменовані обсяги - це чудовий підхід. Підказка: переконайтеся, що ви не використовуєте дефісні назви томів. Ви проведете невелику частину свого життя у нащадному кошмарі, лише дізнавшись, що вас знову обдурив смішний нюанс.
dustintheweb

3
"Зверніть увагу, що докер-композиція знищить ці стійкі томи." Це не вірно в Docker для Mac v 17.0.5+ (і, можливо, більш старих версіях). docker-compose downбуде видалено контейнери, але обсяг збережеться, поки ви не запустите щось на зразокdocker system prune
BrDaHa

3
У випадку, якщо комусь цікаво зрозуміти, чому використання node_modules:названого тома "ігнорує" /app/node_modulesв контейнері докера, це повідомлення може бути корисним, як докер обробляє кілька типів кріплення?
ira

3
Я не знаю, чи роблю я щось не так, але якщо я це роблю, запустіть контейнер, а потім запустіть npm встановити на машині HOST, це також змінює node_modules всередині CONTAINER. Я не можу уявити, чому хто-небудь хотів би це зробити, але все ж шукаю більш чистого розлучення.
Ренра

3
У @Renra була точно така ж проблема, моя хост-машина постійно писала над node_modules, хоча я мав названий том ... викликав усілякі проблеми несумісності. Кинув на її виправлення та працював навколо нього тільки копіюючи мою папку Src замість цілого репо
dancypants

19

Щоб виключити файл, скористайтеся наступним

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded

6
Ідеальне рішення для того, що мені було потрібно (НЕ відображати node_modules до хоста, тому що символи посилань зламалися на хості Windows). Вказівка ​​на / dev / null не спрацювала, але створити порожній каталог і відобразити його до того, що працювало чудово і вирішив проблеми, які у мене виникли - дякую за цю ідею.
Ліам Хаммет

1
Це не працює в Docker для Mac 18.09.0: Cannot start service xxx: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/dev/null\\\" to rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged\\\" at [...] unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. Додавання останньої косої риски не допомогло.
Блейз

Я можу підтвердити, що він не працює ні на Ubuntu 16.04 з Docker 18.09.3.
Дірк

Це не працює для мене. Все, що він робить, - це копія /dev/nullв контейнер, як файл пристрою.
Радон Росборо

1
Зверніть увагу, що це працює лише для виключення ФАЙЛІВ! / DEV / нуль є файлом , і так має бути метою, повідомлення про помилку абсолютно ясно про це: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. Це не саме те, що шукала ОП, але це було дуже корисно для мене, оскільки мені потрібно було виключити один файл.
Авій

13

По-перше, використання ADDінструкції в Dockerfile сильно відрізняється від використання тома (або через -vаргумент до, docker runабо з VOLUMEінструкцією в Dockerfile). Команди ADDі і COPYпросто беруть копію файлів під час docker buildзапуску. Ці файли не оновлюються, поки з docker buildкомандою не буде створено свіже зображення . Навпаки, використання тома по суті говорить "цей каталог не повинен зберігатися у зображенні контейнера; натомість використовувати каталог на хості"; кожного разу, коли файл усередині тома буде змінено, і хост і контейнер побачать його негайно.

Я не вірю, що ви можете досягти того, що ви хочете, використовуючи томи, вам доведеться переглянути свою структуру каталогів, якщо ви хочете це зробити.

Однак досягти використання COPY(що слід віддати перевагу ADD) досить просто . Ви можете використовувати .dockerignoreфайл, щоб виключити підкаталог, або ви можете COPYвсі файли потім зробити, RUN rm blaщоб видалити підкаталог.

Пам’ятайте, що будь-які файли, які ви додаєте до зображення за допомогою COPYабо ADDповинні знаходитись у контексті збирання, тобто в каталозі або нижче, з якого ви запускаєтесь docker build.


1
щодня дізнайтеся щось нове :-) COPY і ADD працюють з контексту складання (не від хоста). Чи можна було б використовувати том для маскування підпапки? ОП хоче встановити / hostFolder (я думаю), і зробити / hostFolder / subFolder відключеним. Якби був VOLUME для кожного, але було встановлено лише hostFolder (-v), чи це ізолювати зміни підпапки в контейнері?
Грег

Я не впевнений, я ніколи не пробував гніздування обсягів. Я не переконаний, що це гарна ідея, але мені доведеться розглянути її.
Адріан Муат

1
Я не можу ніде знайти приклад того, що потрібно помістити у .dockerignoreфайл, щоб виключити підкаталог (або навіть каталог). Враховуючи, що це заявлене призначення файлу, це досить дивно.
Лукас Оберхубер

1
як тільки ви додасте будь-які файли, вони все ще залишаються в деяких шарах. Таким чином, видалення з них не допоможе вам приховати їх, якщо залежно від безпеки або зменшить розмір зображення (оскільки вони будуть знаходитись у нижчих шарах). Існують варіанти squashшарів. Один - github.com/goldmann/docker-squash, а інший використовується oc ex dockerbuildдля проекту openhift.
акостадінов

6

Схоже, старе рішення більше не працює (принаймні для мене). Створення порожньої папки та відображення цільової папки до неї допомогло.

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/

Не працює для мене, з docker-compose 1.25.0-rc3синтаксисом файлу v3.
thisismydesign

6

За допомогою командного рядка docker:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...

-vОпція також може бути використана (кредит Богданом Mart ), але --mountясніше і рекомендуються .


6

для людей, які також мали проблему, що папка node_modules все одно перезапишеться з вашої локальної системи та навпаки

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules/

Це рішення, /коли виправлення слід після модулів node_.


0

Щоб виключити змонтований файл, що міститься в томі вашого пристрою, вам доведеться перезаписати його, виділивши цей же файл. У своєму конфігураційному файлі:

services:
  server:
    build : ./Dockerfile
    volumes:
      - .:/app

Приклад у вашому dockerfile:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.