Как смонтировать локальные тома в докер-машине

85

Я пытаюсь использовать docker-machine с docker-compose. Файл docker-compose.yml имеет следующие определения:

web:
  build: .
  command: ./run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

При запуске docker-compose up -dвсе идет хорошо, пока не попытается выполнить команду и не выдаст ошибку:

Не удается запустить контейнер b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d: [8] Системная ошибка: exec: "./run_web.sh": stat ./run_web.sh: нет такого файла или каталога

Локальные тома не подключаются к удаленному компьютеру. Какая стратегия рекомендуется для монтирования локальных томов с помощью кода веб-приложений?

jdcaballerov
источник
Структура проекта и docker-compose.yml аналогична этому руководству syncano.com/…
jdcaballerov
1
Это должно быть в документах docker-compose в качестве полезной подсказки для тех, кто может начать использовать compose локально. Сэкономил бы мне часы WTF моментов, пытаясь выяснить, почему, черт возьми, мой путь к файлу был неправильным или не был найден. Нет, я просто чувствую себя глупо.
timbrown

Ответы:

93

Docker-machine автоматически монтирует каталог пользователей ... Но иногда этого просто недостаточно.

Не знаю про докер 1.6, но в 1.8 МОЖНО добавить дополнительное крепление к докер-машине

Добавление точки подключения виртуальной машины (часть 1)

CLI : (работает только когда машина остановлена)

VBoxManage sharedfolder add <machine name/id> --name <mount_name> --hostpath <host_dir> --automount

Таким образом, пример в окнах будет

/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe sharedfolder add default --name e --hostpath 'e:\' --automount

GUI : (НЕ требует остановки машины)

  1. Запустите "Oracle VM VirtualBox Manager"
  2. Щелкните правой кнопкой мыши <machine name>(по умолчанию)
  3. Настройки ...
  4. Общие папки
  5. Папка + значок справа (Добавить общий ресурс)
  6. Путь к папке: <host dir>(e :)
  7. Имя папки: <mount name>(e)
  8. Отметьте «Авто-монтирование» и «Сделать постоянным» (Прочтите только, если хотите ...) (В настоящее время автоматическое монтирование бессмысленно ...)

Монтирование в boot2docker (часть 2)

Смонтировать вручную в boot2docker :

  1. Существуют различные способы входа в систему, использование «Показать» в «Oracle VM VirtualBox Manager» или ssh / putty в докере по IP-адресу docker-machine ip defaultи т. Д.
  2. sudo mkdir -p <local_dir>
  3. sudo mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>

Но это хорошо только до тех пор, пока вы не перезапустите машину, а затем монтирование потеряно ...

Добавление автомонтирования в boot2docker :

Пока авторизовался в машине

  1. Редактировать / создавать (как root) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 может быть другим для вас ...
  2. Добавить

    mkdir -p <local_dir>
    mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
    

С этими изменениями у вас должна быть новая точка монтирования. Это один из немногих файлов, который я смог найти, который вызывается при загрузке и является постоянным. Пока не будет лучшего решения, это должно сработать.


Старый метод: реже рекомендуется , но оставлен как альтернатива

  • Отредактируйте (как root) /mnt/sda1/var/lib/boot2docker/profile, sda1 может быть другим для вас ...
  • Добавить

    add_mount() {
      if ! grep -q "try_mount_share $1 $2" /etc/rc.d/automount-shares ; then
        echo "try_mount_share $1 $2" >> /etc/rc.d/automount-shares
      fi
    }
    
    add_mount <local dir> <mount name>
    

В крайнем случае , вы можете выбрать более утомительную альтернативу и просто изменить загрузочный образ.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 # или ваша соответствующая версия
  • редактировать rootfs/etc/rc.d/automount-shares
  • Добавьте try_mount_share <local_dir> <mount_name>строку прямо перед fi в конце. Например

    try_mount_share /e e
    

    Только убедитесь, что не устанавливаете ничего, что нужно операционной системе, например / bin и т. Д.

  • docker build -t boot2docker . # В первый раз это займет около часа :(
  • docker run --rm boot2docker > boot2docker.iso
  • Сделайте резервную копию старого boot2docker.iso и скопируйте новый на его место в ~ / .docker / machine / machines /

Это действительно работает, это просто долго и сложно

докер версия 1.8.1, докер-машина версия 0.4.0

Энди
источник
Для тех, у кого есть проблемы с этим, я почти уверен, что мне пришлось сделать так, чтобы локальные пути совпадали с путями в докер-машине. Также docker-compose, похоже, смонтировал тома, а обычный докер - нет - не знаю, почему.
Spieden
3
Создал сценарий для упомянутого здесь решения. Работает на последних версиях docker 1.10 и docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal
Об использовании говорят разные ресурсы /mnt/sda1/var/lib/boot2docker/profile, можете ли вы объяснить, почему вы перешли на использование /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Кроме того, выделение такого большого количества текста не способствует удобочитаемости вашего ответа ;-)
Forage
1
@Forage Точка зрения о моем форматировании :). Я уже не помню, почему я предлагаю этот bootlocal.shметод. Все, что я могу сказать, это выглядит проще, если просто использовать команду монтирования, как это сделал я, bootlocal.shчем в профиле. Кроме того, обычно я считаю, что profileего можно запускать несколько раз, а монтирование нужно запускать только один раз, поэтому это имеет больше смысла. Но оба могут работать.
Энди
ЛЮБИТЬ ЭТО! Спасибо!
Qorbani
28

Также столкнулся с этой проблемой, и похоже, что локальные тома не монтируются при использовании докер-машины. Хакерское решение -

  1. получить текущий рабочий каталог экземпляра докер-машины docker-machine ssh <name> pwd

  2. используйте инструмент командной строки, например, rsyncскопируйте папку в удаленную систему

    rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:<result _of_pwd_from_1>.
    

По умолчанию pwd - / root, поэтому приведенная выше команда будет rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

NB: вам нужно будет указать пароль для удаленной системы. Вы можете быстро создать его с помощью ssh в удаленной системе и создать пароль.

  1. измените точку монтирования тома в вашем docker-compose.ymlфайле с .:/appна/root/<name_of_folder>:/app

  2. бегать docker-compose up -d

NB, когда изменения вносятся локально, не забудьте перезапустить, rsyncчтобы отправить изменения в удаленную систему.

Это не идеально, но работает. Проблема не решена https://github.com/docker/machine/issues/179

Другой проект, который пытается решить эту проблему, включает docker-rsync

gbozee
источник
rsync необходимо установить в удаленной системе, кажется, `sh: rsync: not found rsync: соединение неожиданно закрыто (получено 0 байт) [отправитель] ошибка rsync: удаленная команда не найдена (код 127) в / SourceCache / rsync / rsync -45 / rsync / io.c (453) [sender = 2.6.9] `Как вы заставили его работать?
krinker
1
rsync необходимо установить в вашей локальной системе
gbozee
Использование этих шагов полностью блокирует мой хост digitalocean. Файлы передаются нормально, но когда я пытаюсь повторно подключиться к хосту с помощью докер-машины, мне exit status 255приходится полностью воссоздавать машину.
dsifford
1
Создал сценарий для упомянутого здесь решения. Работает на latest docker 1.10и docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
кристобаль
@cristobal похоже, что вы написали сценарий для решения монтирования, а не для решения rsync?
Энди
14

На данный момент я не вижу способа монтировать тома на машинах, поэтому подход к настоящему моменту заключался бы в том, чтобы как-то скопировать или синхронизировать файлы, которые вам нужны, на машине.

Есть разговоры о том , как решить эту проблему на GitHub репо докер-машины. Кто-то сделал запрос на перенос, реализующий scp на докер-машине, и он уже объединен на master, поэтому очень вероятно, что следующий выпуск будет включать его.

Поскольку он еще не выпущен, я бы порекомендовал, если у вас есть код, размещенный на github, просто клонируйте свое репо, прежде чем запускать приложение.

web:
  build: .
  command: git clone https://github.com/my/repo.git; ./repo/run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Обновление: глядя дальше, я обнаружил, что эта функция уже доступна в последних двоичных файлах , когда вы их получите, вы сможете скопировать свой локальный проект, выполнив команду, подобную этой:

docker-machine scp -r . dev:/home/docker/project

Это общая форма:

docker-machine scp [machine:][path] [machine:][path]

Таким образом, вы можете копировать файлы с компьютеров и на них.

Ура! 1

Claudevandort
источник
документация для docker-machine scp: docs.docker.com/machine/reference/scp
Энтони Даханн,
2
этот метод очень медленный :(
Сергей Евсеев
5

С октября 2017 года появилась новая команда для docker-machine, которая делает трюк, но перед ее выполнением убедитесь, что в каталоге ничего нет, иначе она может потеряться:

docker-machine mount <machine-name>:<guest-path> <host-path>

Дополнительную информацию см. В документации: https://docs.docker.com/machine/reference/mount/

PR с изменением: https://github.com/docker/machine/pull/4018

Хорхе
источник
1
Просто невероятно, из документации Docker Machine (которую вы связали) - буквально - невозможно узнать, что порядок в команде ...:<guest-path> <host-path>(а не наоборот). Что-то такое простое и важное, что нужно отметить в документации ... просто нет!
Дэн Ниссенбаум
Я думаю, это не очень однозначно, вы правы. Об этом следует догадываться по списку команд
Хорхе
Это делает свое дело, но другим способом. Это позволяет монтировать каталог докер-машины на вашем локальном компьютере. К сожалению, другого пути он не допускает :(
ravenwing
4

Если вы выберете опцию rsync с docker-machine, вы можете комбинировать ее с docker-machine ssh <machinename>командой следующим образом:

rsync -rvz --rsh='docker-machine ssh <machinename>' --progress <local_directory_to_sync_to> :<host_directory_to_sync_to>

Он использует этот формат команды rsync, оставляя HOSTпустым:

rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST

( http://linuxcommand.org/man_pages/rsync1.html )

dmh
источник
1

Наконец выяснилось, как обновить Windows Docker Toolbox до версии v1.12.5 и сохранить работу моих томов, добавив общую папку в Oracle VM VirtualBoxдиспетчере и отключив преобразование пути. Если у вас Windows 10+, вам лучше использовать новую версию Docker для Windows.

1-е обновление Боль:

  1. Сначала удалите VirtualBox.
    • Да, это может сломать работу других инструментов, таких как Android Studio. Спасибо, Докер :(
  2. Установите новую версию Docker Toolbox.

Пример базы данных Redis: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

В терминале быстрого запуска Docker ....

  1. run docker-machine stop default- Убедитесь, что виртуальная машина подключена

В Oracle VM VirtualBox Manager ...

  1. Добавлена ​​общая папка в defaultВМ через или командную строку
    • D:\Projects\MyProject\db => /var/db

В docker-compose.yml...

  1. Отображенный том redis как: "/var/db/redis:/data:rw"

В терминале быстрого запуска Docker ....

  1. Задавать COMPOSE_CONVERT_WINDOWS_PATHS=0 (для версии Toolbox> = 1.9.0)
  2. запустить, docker-machine start defaultчтобы перезапустить виртуальную машину.
  3. cd D:\Projects\MyProject\
  4. docker-compose up должен работать сейчас.

Теперь создает базу данных Redis в D:\Projects\MyProject\db\redis\dump.rdb

Зачем избегать относительных путей к хостам?

Я избегал относительных путей хоста для Windows Toolbox, так как они могут вводить недопустимые символы '\'. Это не так хорошо, как использование путей относительно, docker-compose.ymlно, по крайней мере, мои коллеги-разработчики могут легко это сделать, даже если их папка проекта находится в другом месте, без необходимости взламыватьdocker-compose.yml файл (плохо для SCM).

Оригинальный выпуск

К вашему сведению ... Вот исходная ошибка, которую я получил, когда использовал хорошие чистые относительные пути, которые раньше отлично работали для старых версий. Мое отображение объема раньше было просто"./db/redis:/data:rw"

ERROR: for redis Cannot create container for service redis: Invalid bind mount spec "D:\\Projects\\MyProject\\db\\redis:/data:rw": Invalid volume specification: 'D:\Projects\MyProject\db\redis:/data

Это не работает по двум причинам.

  1. Нет доступа к D:диску
  2. Пути к томам не могут включать \символы
    • docker-compose добавляет их, а затем обвиняет вас в этом !!
    • Используйте, COMPOSE_CONVERT_WINDOWS_PATHS=0чтобы остановить эту чушь.

Я рекомендую задокументировать ваше дополнительное сопоставление общих папок виртуальной машины в вашем docker-compose.ymlфайле, поскольку вам может потребоваться снова удалить VirtualBox и сбросить общую папку, и в любом случае ваши коллеги-разработчики полюбят вас за это.

Тони О'Хаган
источник
вы, сэр, прекрасный человек
AaronHS
1

Все остальные ответы были хорошими для того времени, но теперь (Docker Toolbox v18.09.3) все работает из коробки. Вам просто нужно добавить общую папку в VirtualBox VM.

Docker Toolbox автоматически добавляется в C:\Usersкачестве общей папки на /c/Usersвиртуальной машине Linux (с использованием функции общих папок Virtual Box), поэтому, если ваш docker-compose.ymlфайл находится где-то по этому пути, и вы подключаете каталоги хост-машины только по этому пути - все должно работать из коробки.

Например:

C:\Users\username\my-project\docker-compose.yml:

...
  volumes:
    - .:/app
...

.Путь будет автоматически преобразован в абсолютный путь , C:\Users\username\my-projectа затем /c/Users/username/my-project. И именно так этот путь видится с точки зрения виртуальной машины linux (вы можете проверить: docker-machine sshа затем ls /c/Users/username/my-project). Итак, финальное крепление будет/c/Users/username/my-project:/app .

У вас все работает прозрачно.

Но это не сработает, если путь монтирования вашего хоста не находится под C:\Usersпутем. Например, если вы поместите то же самое docker-compose.ymlпод D:\dev\my-project.

Однако это можно легко исправить.

  1. Остановите виртуальную машину ( docker-machine stop).
  2. Откройте графический интерфейс Virtual Box, откройте настройки виртуальной машины с именем default, откройте Shared Foldersраздел и добавьте новую общую папку:

    • Путь к папке: D:\dev
    • Имя папки: d/dev

    OKДважды нажмите и закройте графический интерфейс Virtual Box.

  3. Запустите виртуальную машину ( docker-machine start).

Вот и все. Все пути к хост-машине D:\devтеперь должны работать в docker-compose.ymlмонтировках.

Руслан Стельмаченко
источник
1

Это может быть сделано сочетанием ведьмы из трех инструментов: docker-machine mount, rsync,inotifywait

TL; DR

Скрипт, основанный на всем, что ниже, находится здесь

Допустим, у вас есть docker-compose.ymlи run_web.shв/home/jdcaballerov/web

  1. Смонтировать каталог на компьютере , путь к которому тот же , что и на вашем хостеdocker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Синхронизируйте смонтированный каталог с dir на вашем хосте rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Синхронизируйте каждое изменение файлов в вашем каталоге:

    inotifywait -r -m -e close_write --format '%w%f' /home/jdcaballerov/web | while read CHANGED_FILE
    do
        rsync /home/jdcaballerov/web /tmp/some_random_dir
    done
    

БУДЬТЕ ВНИМАТЕЛЬНЫ - есть два каталога с одинаковым путем: один находится на вашем локальном (главном) компьютере, а второй - на докере.

крыло ворона
источник
0

Я предполагаю, что run_web.shфайл находится в том же каталоге, что и ваш docker-compose.ymlфайл. Тогда команда должна быть command: /app/run_web.sh.

Если Dockerfile(что вы не раскрываете) позаботится о помещении run_web.shфайла в образ Docker.

Thomasleveil
источник
спасибо за Ваш ответ. Он находится в том же каталоге. Однако я заметил, что том не монтируется. Файлы недоступны, вот в чем вопрос. Как их добавить. Структура похожа на syncano.com/…
jdcaballerov
Убедитесь, что у вас установлены последние версии как docker, так и dicker-compose.
Thomasleveil
docker: Docker версия 1.6.0, сборка 4749651, docker-machine версия 0.2.0 (8b9eaf2), docker-compose 1.2.0
jdcaballerov
Вы каким- либо образом модифицировали файл Dockerfile с сайта syncano.com/… ?
Thomasleveil
1
Да, я добавляю код, создаю каталог. Проблема в том, что при выполнении docker-compose перезаписывает volume: volume: -.: / App и оставляет пустой каталог. Я прокомментировал тома в сочинении, и это работает.
jdcaballerov
0

После обобщения сообщений здесь прилагается обновленный скрипт для создания дополнительной точки подключения хоста и автоматического монтирования при перезапуске Virtualbox. Краткое описание рабочей среды, как показано ниже: - Windows 7 - docker-machine.exe версия 0.7.0 - VirtualBox 5.0.22

    #!env bash

    : ${NAME:=default}
    : ${SHARE:=c/Proj}
    : ${MOUNT:=/c/Proj}
    : ${VBOXMGR:=C:\Program Files\Oracle\VirtualBox\VBoxManage.exe}
    SCRIPT=/mnt/sda1/var/lib/boot2docker/bootlocal.sh

    ## set -x
    docker-machine stop $NAME
    "$VBOXMGR" sharedfolder add $NAME --name c/Proj --hostpath 'c:\' --automount 2>/dev/null || :
    docker-machine start $NAME
    docker-machine env $NAME

    docker-machine ssh $NAME 'echo "mkdir -p $MOUNT" | sudo tee $SCRIPT'
    docker-machine ssh $NAME 'echo "sudo mount -t vboxsf -o rw,user $SHARE $MOUNT" |  sudo tee -a $SCRIPT'
    docker-machine ssh $NAME 'sudo chmod +x /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    docker-machine ssh $NAME 'sudo /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    #docker-machine ssh $NAME 'ls $MOUNT'
Джесси
источник
0

Я использую докер-машину 0.12.2 с диском виртуального бокса на моем локальном компьютере. Я обнаружил, что есть каталог, /hosthome/$(user name)из которого у вас есть доступ к локальным файлам.

Бенджамин Слабберт
источник
0

Просто подумал, что упомянул, что использую 18.03.1-ce-win65 (17513) в Windows 10, и я заметил, что если вы ранее использовали общий диск и кешировали учетные данные, после смены пароля в докере появится тома, смонтированные внутри контейнеров, как пустые.

Это не указывает на то, что на самом деле происходит то, что теперь не удается получить доступ к общему ресурсу со старыми кэшированными учетными данными. Решение в этом сценарии состоит в том, чтобы сбросить учетные данные либо через пользовательский интерфейс (Настройки-> Общие диски), либо отключить совместное использование рендерируемого диска и ввести новый пароль.

Было бы полезно, если бы docker-compose выдавал ошибку в этих ситуациях.

Nrjohnstone
источник