Як змонтувати локальні томи в докер-машині


85

Я намагаюся використовувати docker-машину з 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: такого файлу або каталогу немає

Локальні томи не підключаються до віддаленої машини. Яка рекомендована стратегія монтування локальних томів за допомогою коду веб-додатків?


Структура проекту та docker
compose.yml

1
Це повинно бути в документах докеру для складання, як корисний підказка тим, хто, можливо, починає використовувати локальне складання. Заощадив би мені години WTF-моментів, намагаючись зрозуміти, чому, моє, шлях до файлу помилковий чи не знайдений. Ні, я просто почуваюся безглуздо.
timbrown

Відповіді:


93

Docker-машина автоматично монтує каталог користувачів ... Але іноді цього просто недостатньо.

Я не знаю про docker 1.6, але в 1.8 ви МОЖЕТЕ додати додаткове кріплення до docker-машини

Додати точку кріплення віртуальної машини (частина 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. Редагувати / створювати (як корінь) /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>
    

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


Старий метод: Менш рекомендується , але залишається як альтернатива

  • Редагувати (як корінь) /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 /

Це працює, це просто довго і складно

docker версії 1.8.1, docker-версії версії 0.4.0


Для тих, хто має проблеми з цим, я майже впевнений, що мені довелося змусити локальні шляхи збігатися з тими, що знаходяться в докер-машині. Також докер-компонування, здавалося, вдалося змонтувати томи, тоді як звичайний докер не зробив - не впевнений, чому.
spieden

3
Створив сценарій для згаданого тут рішення. Працює на останньому docker 1.10 та докер-машині 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal

Різні ресурси говорять про використання /mnt/sda1/var/lib/boot2docker/profile, чи можете ви пояснити, чому ви перейшли на використання /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Крім того , б'ючи по цьому багато тексту не сприяє читабельності вашої відповіді ;-)
Корми

1
@Forage Point взяв про моє форматування :). Я не пам'ятаю відразу, чому я пропоную bootlocal.shметод. Все, що я можу сказати, це виглядає чистіше просто використовувати команду монтування, як це робив я, bootlocal.shніж це робить у профілі. Крім того, як правило, я вважаю, що profileмогло виконуватися кілька разів, а монтування потрібно запускати лише один раз, тому це має більше сенсу. Але обидва можуть працювати.
Енді

ЛЮБИТЬ ЦЕ! Дякую!
Корбані,

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

Примітка: вам потрібно буде вказати пароль для віддаленої системи. Ви можете швидко створити його за допомогою ssh у віддаленій системі та створити пароль.

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

  2. бігти docker-compose up -d

Зверніть увагу, коли зміни вносяться локально, не забудьте виконати повторно, rsyncщоб внести зміни у віддалену систему.

Це не ідеально, але це працює. Випуск триває https://github.com/docker/machine/issues/179

Інший проект, який намагається вирішити цю проблему, включає docker-rsync


rsync потрібно встановити у віддаленій системі здається `sh: rsync: не знайдено rsync: з'єднання несподівано закрито (до цього часу отримано 0 байт) [відправник] Помилка rsync: віддалена команда не знайдена (код 127) в / SourceCache / rsync / rsync -45 / rsync / io.c (453) [sender = 2.6.9] `Як ви змусили його працювати?
krinker

1
rsync потрібно встановити у вашій локальній системі
gbozee,

Використовуючи ці кроки, повністю блокується мій цифровий хост .. Файли передаються нормально, але коли я намагаюся підключитися до хоста за допомогою докер-машини, я отримую exit status 255і маю повністю відтворити машину.
dsifford

1
Створив сценарій для згаданого тут рішення. Працює над останніми docker 1.10та docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal

@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


документація для docker-машини 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 )


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. запустити docker-machine stop default- переконайтеся, що VM отримано халтуру

В Oracle VM VirtualBox Manager ...

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

У docker-compose.yml...

  1. Назначений обсяг редису як: "/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, оскільки вони можуть вводити недійсні символи '\'. Це не так приємно, як використання шляхів щодо, docker-compose.ymlале, принаймні, мої колеги-розробники можуть це легко зробити, навіть якщо їх папка проекту знаходиться в іншому місці без необхідності злому docker-compose.ymlфайлу (погано для SCM).

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

FYI ... Ось оригінальна помилка, яку я отримав, коли використовував хороші чисті відносні шляхи, які раніше прекрасно працювали для старих версій. Моє відображення обсягу раніше було справедливим"./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. Синхронізуйте змонтований каталог з директорією на вашому хості 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.


Дякую за вашу відповідь. Він знаходиться в одному каталозі. Однак я помічаю, що гучність не монтується. Файли недоступні, і в цьому питання. Як їх додати. Структура подібна до syncano.com/…
jdcaballerov

Переконайтеся, що у вас є найновіші версії як докера, так і дікера.
Томаслевей

docker: Docker версія 1.6.0, збірка 4749651, докер-машина версії 0.2.0 (8b9eaf2), docker-compose 1.2.0
jdcaballerov

Ви будь-яким чином змінили файл Docker із сайту syncano.com/… ?
Томаслевей

1
Так, я додаю код, створюю каталог. Проблема в тому, що при виконанні docker-compose він перезаписує том: 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

Я використовую docker-machine 0.12.2 з диском virtualbox на своїй локальній машині. Я виявив, що існує каталог, /hosthome/$(user name)звідки ви маєте доступ до локальних файлів.


0

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

Це не вказує на те, що насправді відбувається те, що зараз він не може отримати доступ до спільних даних зі старими кешованими обліковими даними. Рішенням у цьому сценарії є скидання облікових даних або через інтерфейс користувача (Налаштування-> Спільні диски), або вимкнути, а потім увімкнути спільний доступ до дисків та ввести новий пароль.

Було б корисно, якщо docker-compose видав помилку в цих ситуаціях.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.