Как смонтировать каталог хоста в Docker-контейнере
Я пытаюсь смонтировать каталог хоста в контейнер Docker, чтобы любые обновления, сделанные на хосте, отражались в контейнерах Docker. Я не смог добиться успеха после поиска в Google и чтения ссылок на тома Docker.
Где я делаю что-то не так. Вот что я сделал:
kishore$ cat Dockerfile
FROM ubuntu:trusty
RUN apt-get update
RUN apt-get -y install git curl vim
CMD ["/bin/bash"]
WORKDIR /test_container
VOLUME ["/test_container"]
kishore$ tree
.
├── Dockerfile
└── main_folder
├── tfile1.txt
├── tfile2.txt
├── tfile3.txt
└── tfile4.txt
1 directory, 5 files
kishore$ pwd
/Users/kishore/tdock
kishore$ docker build --tag=k3_s3:latest .
Uploading context 7.168 kB
Uploading context
Step 0 : FROM ubuntu:trusty
---> 99ec81b80c55
Step 1 : RUN apt-get update
---> Using cache
---> 1c7282005040
Step 2 : RUN apt-get -y install git curl vim
---> Using cache
---> aed48634e300
Step 3 : CMD ["/bin/bash"]
---> Running in d081b576878d
---> 65db8df48595
Step 4 : WORKDIR /test_container
---> Running in 5b8d2ccd719d
---> 250369b30e1f
Step 5 : VOLUME ["/test_container"]
---> Running in 72ca332d9809
---> 163deb2b1bc5
Successfully built 163deb2b1bc5
Removing intermediate container b8bfcb071441
Removing intermediate container d081b576878d
Removing intermediate container 5b8d2ccd719d
Removing intermediate container 72ca332d9809
kishore $ docker run -d -v / Users / kishore / main_folder: / test_container k3_s3: последний c9f9a7e09c54ee1c2cc966f15c963b4af320b5203b8c46689033c1ab8872a0ea
kishore$ docker run -i -t k3_s3:latest /bin/bash
root@0f17e2313a46:/test_container# ls -al
total 8
drwx------ 2 root root 4096 Apr 29 05:15 .
drwxr-xr-x 66 root root 4096 Apr 29 05:15 ..
root@0f17e2313a46:/test_container# exit
exit
kishore$ docker -v
Docker version 0.9.1, build 867b2a9
- Я не знаю, как проверить версию boot2docker
Вопросы, проблемы, с которыми сталкиваются:
- Как мне нужно связать main_folder с папкой test_container, которая находится внутри контейнера Docker?
- Мне нужно сделать это автоматически. Как мне это сделать, не используя
run -d -v
команда? - Что произойдет, если сбой boot2docker? Где хранятся файлы Docker (кроме Dockerfile)?
27 ответов
Есть несколько способов сделать это. Самый простой способ сделать это - использовать dockerfile ADD
команда вроде так:
ADD . /path/inside/docker/container
Однако любые изменения, внесенные в этот каталог на хосте после сборки файла dockerfile, не будут отображаться в контейнере. Это связано с тем, что при сборке контейнера Docker сжимает каталог в .tar
и загружает этот контекст в контейнер постоянно.
Второй способ сделать это - способ, которым вы пытались, - это смонтировать том. Из-за того, что вы пытаетесь быть максимально переносимым, вы не можете сопоставить каталог хоста с каталогом контейнера докера в файле Docker, потому что каталог хоста может меняться в зависимости от того, на какой машине вы работаете. Чтобы отобразить каталог хоста в каталог контейнера докера, вам нужно использовать -v
флаг при использовании Docker запускается так:
docker run -v /host/directory:/container/directory -other -options image_name command_to_run
Пользователь этого вопроса использовал Docker version 0.9.1, build 867b2a9
Я дам ответ для версии докера>= 17.06.
То, что вы хотите, синхронизируйте локальный каталог внутри каталога контейнера, достигается монтированием тома с типом bind
, Это свяжет исходные (ваша система) и целевые (в контейнере Docker) каталоги. Это почти то же самое, что монтировать каталог в Linux.
Согласно документации Docker, соответствующая команда для монтирования теперь mount
вместо -v
, Вот его документация:
--mount
: Состоит из нескольких пар ключ-значение, разделенных запятыми. Каждая пара ключ / значение принимает форму<key>=<value>
кортеж.--mount
синтаксис более многословен, чем-v
или же--volume
, но порядок ключей не имеет значения, а значение флага легче понять.type
горы, которая может бытьbind
,volume
, или жеtmpfs
, (Мы собираемся использовать Bind)source
горы. Для bind mounts это путь к файлу или каталогу на хосте демона Docker. Может быть указан какsource
или жеsrc
,destination
принимает в качестве значения путь, по которому файл или каталог будут смонтированы в контейнере. Может быть указан какdestination
,dst
, или жеtarget
,
Итак, чтобы смонтировать текущий каталог (источник) с /test_container
(цель) мы будем использовать:
docker run -it --mount src="$(pwd)",target=/test_container,type=bind k3_s3
Если эти параметры монтирования имеют пробелы, вы должны заключить их в кавычки. Когда я знаю, что нет, я бы использовал `pwd`
вместо:
docker run -it --mount src=`pwd`,target=/test_container,type=bind k3_s3
Вам также придется иметь дело с разрешением файла, см. Эту статью.
Вы можете использовать опцию -v из cli, эта возможность недоступна через Dockerfile
docker run -t -i -v <host_dir>:<container_dir> ubuntu /bin/bash
где host_dir - каталог с хоста, который вы хотите смонтировать. вам не нужно беспокоиться о каталоге контейнера, если он не существует, Docker создаст его.
Если вы сделаете какие-либо изменения в host_dir с хоста (под привилегией root), он будет виден контейнеру и наоборот.
2 последовательных монтирования: я полагаю, что во многих постах здесь может использоваться два boot2docker, потому что вы ничего не видите, потому что вы монтируете каталог из boot2docker, а не с вашего хоста. В основном вам нужно 2 последовательных монтирования: первое для монтирования каталога с вашего хоста в вашу систему, а второе для монтирования нового каталога из boot2docker в ваш контейнер, например так:
1. смонтировать локальную систему на boot2docker
sudo mount -t vboxsf hostfolder /boot2dockerfolder
2. смонтировать файл boot2docker на контейнер linux
docker run -v /boot2dockerfolder:/root/containerfolder -i -t imagename
тогда, когда ты ls
внутри контейнерной папки вы увидите содержимое вашей хост-папки
Для тех, кто хочет смонтировать папку в текущем каталоге:
docker run -d --name some-container -v ${PWD}/folder:/var/folder ubuntu
Возможно ли, что вы используете Docker на OS X через boot2docker
или что-то подобное.
Я сделал то же самое - команда верна, но в контейнере ничего (разумного) все равно не монтируется.
Как оказалось - это уже объяснено в документации докера. Когда вы печатаете docker run -v /var/logs/on/host:/var/logs/in/container ...
затем /var/logs/on/host
на самом деле отображается из boot2docker
VM-образ, а не ваш Mac.
Вам нужно будет передать общую папку через виртуальную машину на ваш реальный хост (в моем случае это Mac).
Я просто экспериментирую с тем, чтобы мое приложение SailsJS работало внутри контейнера Docker, чтобы поддерживать чистоту моей физической машины.
Я использую следующую команду для монтирования моего приложения SailsJS/NodeJS в / app:
cd my_source_code_folder docker run -it -p 1337: 1337 -v $ (pwd): / app my_docker / image_with_nodejs_etc
[ОБНОВЛЕНИЕ] Начиная с ~ июня 2017 года, Docker для Mac позаботился обо всех раздражающих частях этого, где вы должны связываться с VirtualBox. Это позволяет вам сопоставить практически все на вашем локальном хосте, используя /private
префикс. Больше информации здесь. [/ОБНОВИТЬ]
Все текущие ответы говорят о Boot2docker. Так как теперь это не рекомендуется в пользу docker-machine, это работает для docker-machine:
Сначала вставьте ssh в docker-machine vm и создайте папку, в которую мы будем отображать:
docker-machine ssh $MACHINE_NAME "sudo mkdir -p \"$VOL_DIR\""
Теперь поделитесь папкой с VirtualBox:
WORKDIR=$(basename "$VOL_DIR")
vboxmanage sharedfolder add "$MACHINE_NAME" --name "$WORKDIR" --hostpath "$VOL_DIR" --transient
Наконец, снова вставьте ssh в докер и подключите папку, к которой мы только что поделились:
docker-machine ssh $MACHINE_NAME "sudo mount -t vboxsf -o uid=\"$U\",gid=\"$G\" \"$WORKDIR\" \"$VOL_DIR\""
Примечание: для UID и GID вы можете использовать любые целые числа, если они еще не заняты.
Это проверено на докер-машине 0.4.1 и докере 1.8.3 на OS X El Capitan.
С помощью command-line
:
docker run -it --name <WHATEVER> -p <LOCAL_PORT>:<CONTAINER_PORT> -v <LOCAL_PATH>:<CONTAINER_PATH> -d <IMAGE>:<TAG>
С помощью docker-compose.yaml
:
version: '2'
services:
cms:
image: <IMAGE>:<TAG>
ports:
- <LOCAL_PORT>:<CONTAINER_PORT>
volumes:
- <LOCAL_PATH>:<CONTAINER_PATH>
Предполагать:
- ИЗОБРАЖЕНИЕ: k3_s3
- ТЕГ: последний
- LOCAL_PORT: 8080
- КОНТЕЙНЕРНЫЙ_ПОРТ: 8080
- LOCAL_PATH: / объем-к-монтированию
- CONTAINER_PATH: / mnt
Примеры:
- Сначала создайте /volume-to-mount. (Пропустить, если есть)
$ mkdir -p /volume-to-mount
- docker-compose -f docker-compose.yaml вверх -d
version: '2'
services:
cms:
image: ghost-cms:latest
ports:
- 8080:8080
volumes:
- /volume-to-mount:/mnt
- Проверьте свой контейнер:
docker exec -it CONTAINER_ID ls -la /mnt
docker run -v /host/directory:/container/directory -t IMAGE-NAME /bin/bash
docker run -v /root/shareData:/home/shareData -t kylemanna/openvpn /bin/bash
В моей системе я исправил ответ от nhjk, он работает безупречно, когда вы добавляете -t
флаг.
В Mac OS для монтирования папки /Users/<name>/projects/
на вашем Mac в корне вашего контейнера:
docker run -it -v /Users/<name>/projects/:/projects <container_name> bash
ls /projects
Если хост - это Windows 10, то вместо прямой косой черты используйте обратную косую черту -
docker run -it -p 12001:80 -v c:\Users\C\Desktop\dockerStorage:/root/sketches
Убедитесь, что главный диск является общим (в данном случае C). В моем случае после выполнения приведенной выше команды я получил запрос на разрешение общего доступа.
Для пользователей Windows 10 важно иметь точку монтирования внутри C:/Users/
каталог. Я часами пытался заставить это работать. Этот пост помог, но сначала он не был очевиден, поскольку решение для Windows 10 - это комментарий к принятому ответу. Вот как я это сделал:
docker run -it -p 12001:80 -v //c/Users/C/Desktop/dockerStorage:/root/sketches \
<your-image-here> /bin/bash
Затем, чтобы проверить это, вы можете сделать echo TEST > hostTest.txt
внутри вашего изображения. Вы должны увидеть этот новый файл в папке локального хоста по адресу C:/Users/C/Desktop/dockerStorage/
,
Начиная с Docker 18-CE, вы можете использовать docker run -v /src/path:/container/path
сделать двухстороннее связывание хост-папки.
Здесь есть одна большая загвоздка, если вы работаете с Windows 10/WSL и в качестве хоста используете Docker-CE для Windows, а затем клиентские инструменты docker-ce в WSL. WSL знает обо всей файловой системе /, а ваш хост Windows знает только о ваших дисках. Внутри WSL вы можете использовать /mnt/c/projectpath, но если вы попытаетесь docker run -v ${PWD}:/projectpath
, вы найдете на хосте, что / projectpath / пуст, потому что на хосте / mnt ничего не значит.
Если вы работаете с / c / projectpath, хотя и ТО делаете docker run -v ${PWD}:/projectpath
и вы обнаружите, что в контейнере / projectpath будет отражать / c / projectpath в реальном времени. Там нет ошибок или других способов обнаружить эту проблему, кроме как видеть пустые крепления внутри вашего гостя.
Вы также должны обязательно указать "общий доступ к диску" в настройках Docker для Windows.
У меня была такая же проблема. Моя командная строка выглядела так:
docker run --rm -i --name $NAME -v `pwd`:/sources:z $NAME
Проблема была с "pwd". Поэтому я изменил это на $(pwd):
docker run --rm -i --name $NAME -v $(pwd):/sources:z $NAME
Обновление за июль 2015 года - boot2docker теперь поддерживает прямое монтирование. Ты можешь использовать -v /var/logs/on/host:/var/logs/in/container
прямо из вашего Mac, без двойного монтажа
Как связать main_folder с папкой test_container, находящейся внутри контейнера Docker?
Ваша команда ниже верна, если только вы не используете mac2 с boot2 (в зависимости от будущих обновлений), и в этом случае папка может оказаться пустой. См. Ответ Mattes для учебника по исправлению этого.
docker run -d -v /Users/kishore/main_folder:/test_container k3_s3:latest
Мне нужно сделать этот запуск автоматически, как это сделать без использования команды run -d -v.
Вы не можете уйти от использования этих команд, они являются неотъемлемой частью работы докера. Лучше всего поместить их в сценарий оболочки, чтобы не записывать их повторно.
Что произойдет, если boot2docker вылетит? Где хранятся файлы докеров?
Если вам удастся использовать -v arg и сослаться на ваш хост-компьютер, то файлы будут в безопасности на вашем хосте.
Если вы использовали 'docker build -t myimage.' с Dockerfile ваши файлы будут запечены в образ.
Я полагаю, что ваши образы докеров хранятся в boot2docker-vm. Я узнал об этом, когда мои изображения исчезли, когда я удаляю виртуальную машину из VirtualBox. (Обратите внимание, я не знаю, как работает Virtualbox, поэтому изображения могут быть скрыты где-то еще, просто не видны для докера).
Вот пример с путем Windows:
docker run -P -it --name organizr --mount src="/c/Users/MyUserName/AppData/Roaming/DockerConfigs/Organizr",dst=/config,type=bind organizrtools/organizr-v2:latest
В качестве примечания: во время всего этого растягивания волос, когда приходится ломать голову, придумывать и снова и снова набирать пути, я решил взбить маленький AutoHotkey
скрипт для преобразования пути Windows в путь в формате Docker Windows. Таким образом, все, что мне нужно сделать, - это скопировать любой путь Windows, который я хочу использовать в качестве точки монтирования, в буфер обмена, нажать "клавишу приложений" на клавиатуре, и он отформатирует его в формате пути, который оценит Docker.
Например:
Скопируйте это в буфер обмена:
C:\Users\My PC\AppData\Roaming\DockerConfigs\Organizr
нажмите Apps Key
в то время как курсор находится там, где вы хотите его в командной строке, он вставит его туда:
"/c/Users/My PC/AppData/Roaming/DockerConfigs/Organizr"
Экономит много времени для меня. Вот это для всех, кто может найти это полезным.
; --------------------------------------------------------------------------------------------------------------
;
; Docker Utility: Convert a Windows Formatted Path to a Docker Formatter Path
; Useful for (example) when mounting Windows volumes via the command-line.
;
; By: J. Scott Elblein
; Version: 1.0
; Date: 2/5/2019
;
; Usage: Cut or Copy the Windows formatted path to the clipboard, press the AppsKey on your keyboard
; (usually right next to the Windows Key), it'll format it into a 'docker path' and enter it
; into the active window. Easy example usage would be to copy your intended volume path via
; Explorer, place the cursor after the "-v" in your Docker command, press the Apps Key and
; then it'll place the formatted path onto the line for you.
;
; TODO:: I may or may not add anything to this depending on needs. Some ideas are:
;
; - Add a tray menu with the ability to do some things, like just replace the unformatted path
; on the clipboard with the formatted one rather than enter it automatically.
; - Add 'smarter' handling so the it first confirms that the clipboard text is even a path in
; the first place. (would need to be able to handle Win + Mac + Linux)
; - Add command-line handling so the script doesn't need to always be in the tray, you could
; just pass the Windows path to the script, have it format it, then paste and close.
; Also, could have it just check for a path on the clipboard upon script startup, if found
; do it's job, then exit the script.
; - Add an 'all-in-one' action, to copy the selected Windows path, and then output the result.
; - Whatever else comes to mind.
;
; --------------------------------------------------------------------------------------------------------------
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
AppsKey::
; Create a new var, store the current clipboard contents (should be a Windows path)
NewStr := Clipboard
; Rip out the first 2 chars (should be a drive letter and colon) & convert the letter to lowercase
; NOTE: I could probably replace the following 3 lines with a regexreplace, but atm I'm lazy and in a rush.
tmpVar := SubStr(NewStr, 1, 2)
StringLower, tmpVar, tmpVar
; Replace the uppercase drive letter and colon with the lowercase drive letter and colon
NewStr := StrReplace(NewStr, SubStr(NewStr, 1, 2), tmpVar)
; Replace backslashes with forward slashes
NewStr := StrReplace(NewStr, "\", "/")
; Replace all colons with nothing
NewStr := StrReplace(NewStr, ":", "")
; Remove the last char if it's a trailing forward slash
NewStr := RegExReplace(NewStr, "/$")
; Append a leading forward slash if not already there
if RegExMatch(NewStr, "^/") == 0
NewStr := "/" . NewStr
; If there are any spaces in the path ... wrap in double quotes
if RegExMatch(NewStr, " ") > 0
NewStr := """" . NewStr . """"
; Send the result to the active window
SendInput % NewStr
Я обнаружил, что любой каталог, лежащий под системной директивой вроде /var
, /usr
, /etc
не может быть установлен под контейнером.
Директива должна быть в пространстве пользователя -v
switch указывает демону docker монтировать локальный каталог в контейнер, например:
docker run -t -d -v /{local}/{path}:/{container}/{path} --name {container_name} {imagename}
Была такая же проблема. Нашел это в документации докера:
Примечание. Каталог хоста по своей природе зависит от хоста. По этой причине вы не можете смонтировать каталог хоста из Dockerfile, инструкция VOLUME не поддерживает передачу host-dir, потому что встроенные образы должны быть переносимыми. Каталог хостов не будет доступен на всех потенциальных хостах.
Таким образом, монтирование директории хоста для чтения / записи возможно только с -v
параметр в docker run
команда, так как другие ответы указывают правильно.
Чтобы это работало в Windows 10, мне пришлось открыть окно настроек Docker на панели задач и перейти в раздел " Общие диски ".
Затем я установил флажок рядом с C
. Docker запросил учетные данные моего рабочего стола, чтобы получить разрешение на запись в мою папку "Пользователи".
Затем я запустил контейнер докеров, следуя приведенным выше примерам, а также пример на этой странице настроек, подключившись к /data
в контейнере.
docker run -v c:/Users/<user.name>/Desktop/dockerStorage:/data -other -options
Обратите внимание, что в Windows вам нужно будет указать абсолютный путь.
- Хост: Windows 10
- Контейнер: Блокнот Tensorflow
Ниже работал для меня.
docker run -t -i -v D:/projects/:/home/chankeypathak/work -p 8888:8888 jupyter/tensorflow-notebook /bin/bash
boot2docker вместе с гостевыми дополнениями VirtualBox
Как монтировать / Пользователи в boot2docker
tl; dr Создайте свой собственный boot2docker.iso с гостевыми дополнениями VirtualBox (см. ссылку) или загрузите http://static.dockerfiles.io/boot2docker-v1.0.1-virtualbox-guest-additions-v4.3.12.iso и сохраните его в ~/.boot2docker/boot2docker.iso.
У меня были те же проблемы, я пытался смонтировать папку C:\Users\ на докер
Вот как я это сделал Docker Toolbox из командной строки
$ docker run -it --name <containername> -v /c/Users:/myVolData <imagename>
Вы также можете сделать это с помощью веб-приложения Portainer для другого визуального восприятия.
Сначала вытащите образ Portainer:
docker pull portainer/portainer
Затем создайте том для Portainer:
docker volume create portainer_data
Также создайте контейнер Portainer:
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
Вы сможете получить доступ к веб-приложению в своем браузере по этому URL-адресу: " http://localhost:9000/ ". При первом входе в систему вам будет предложено указать учетные данные администратора Portainer.
В веб-приложении следуйте этим меню и кнопкам: (Контейнер> Добавить контейнер> Параметры заливки > Развернуть контейнер)
У меня возникли проблемы с созданием тома "монтирования" с помощью Portainer, и я понял, что мне нужно нажать "привязать" при создании тома контейнера. Ниже приведена иллюстрация настроек привязки тома, которые работали для моего создания контейнера с подключенным томом, привязанным к хосту.
PS: Я использую Docker 19.035 и Portainer 1.23.1
Цитата с официального сайта :
Убедитесь, что у вас нет запущенных контейнеров для начала работы.
Запустите следующую команду из каталога приложения.
Устройство x86-64 Mac или Linux:
Windows (PowerShell):
docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ node:12-alpine \ sh -c "yarn install && yarn run dev"
Aple Silicon Mac или другое устройство ARM64:
docker run -dp 3000:3000 \\ -w /app -v "$(pwd):/app" \\ node:12-alpine \\ sh -c "apk add --no-cache python2 g++ make && yarn install && yarn run dev"
Объясняя:
-
dp 3000:3000
- так же, как прежде. Запустите в автономном (фоновом) режиме и создайте сопоставление портов. -
w /app
- устанавливает «рабочий каталог» или текущий каталог, из которого будет запускаться команда -
v "$(pwd):/app"
- bind смонтировать текущий каталог с хоста в каталог /app в контейнере -
node:12-alpine
- изображение для использования.
Обратите внимание, что это базовый образ для нашего приложения изDockerfile
sh -c "yarn install && yarn run dev"
- команда.
Мы запускаем оболочку, используяsh
(у alpine нет Bash) и работаетyarn install
установить все зависимости, а затем запустить пряжуrun dev
. Если мы посмотрим вpackage.json
, мы увидим, что скрипт dev запускаетсяnodemon
.
У меня было такое же требование, чтобы смонтировать каталог хоста из контейнера, и я использовал команду тома монтирования. Но во время тестирования заметил, что он также создает файлы внутри контейнера, но после некоторого копания обнаружил, что это просто символические ссылки и фактическая файловая система, используемая с хост-машины.