Як я можу додати том до існуючого контейнера Docker?


297

У мене є контейнер Docker, який я створив, просто встановивши Docker в Ubuntu і виконуючи:

sudo docker run -i -t ubuntu /bin/bash

Я одразу почав встановлювати Java та деякі інші інструменти, провів з нею деякий час і зупинив контейнер

exit

Тоді я хотів додати обсяг і зрозумів, що це не так прямо, як я думав, що це буде. Якщо я використовую, sudo docker -v /somedir run ...то я закінчую новим новим контейнером, тому я мав би встановити Java і робити те, що я вже робив перед тим, як тільки приїхати до контейнера з встановленим обсягом.

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

Це справді єдиний спосіб додати об'єм до наявного контейнера?


1
Після Контейнерів вони стали невід'ємною частиною Програмістів, а отже, такі питання частіше публікуються тут. Питань, розміщених тут, використовуючи dockerтег, - 34k + , що набагато більше, ніж ці два сайти stackoverflow.com/questions/tagged/docker
MA Hossain Tonu

Відповіді:


394

Ви можете скористатися наявним контейнером (тобто створити нове зображення із змін контейнера), а потім запустити його своїми новими кріпленнями.

Приклад:

$ docker ps  -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                          PORTS               NAMES
    5a8f89adeead        ubuntu:14.04          "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       agitated_newton

$ docker commit 5a8f89adeead newimagename

$ docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash

Якщо все гаразд, зупиніть свій старий контейнер і використовуйте цей новий.

Це воно :)


22
І якщо вам потрібен новий контейнер, щоб з якихось причин взяти стару назву, використовуйте перейменування docker після видалення старого.
Дірк

10
просто хотів би зазначити, що вище, де ви згадуєте, newnameofcontainerщо це, мабуть, має бути названо new_image_name- тому що docker commitстворює новий образ у вашій системі. Потім у наступному, коли ви робите a, docker runви фактично використовуєте ім'я зображення, з якого ви хочете запустити новий контейнер. Вищезазначене працює, але просто хотілося уточнити для інших, що нове ім'я контейнера-заповнювача вище є фактично назвою нового зображення. Дякую! приголомшлива відповідь. о, ви можете побачити новостворене зображення з першої команди docker image ls
докера

3
Насправді вам не потрібно вводити новий контейнер, якщо ви хочете почати з зображення. Просто docker run -v /srv/a:/tmp ubuntu:14.04добре.
YongHao Hu

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

Чи збереже це відображення старих томів зі старого контейнера чи я повинен також знову оголосити їх новим контейнером?
thebeancounter

79

У нас немає ніякого способу додавати об'єм у запущеному контейнері, але для досягнення цієї мети ви можете скористатися командами нижче:

Скопіюйте файли / папки між контейнером та локальною файловою системою: -

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Для ознайомлення див:

https://docs.docker.com/engine/reference/commandline/cp/


47
Існує величезна різниця між встановленням тома та копіюванням файлів до та з контейнера ...
Jules

31
Все одно мені це допомогло. Я не знав команди "docker cp" і намагався досягти саме цього - копіюйте файли з запущеного контейнера на хост.
Іван

3
це не кріплення, але зручно повертати файли між контейнером та локальним хостом.
linehrr

Хоча це і вирішує проблему локальної реплікації вмісту контейнера, це не є близьким до монтажу об'єму, і його не слід розглядати як альтернативу. А саме реплікацією повинен керувати користувач, а дані існують зараз у двох місцях.
Себастьян Гаведда

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

33

Я успішно монтую /home/<user-name> папку свого хоста до /mntпапки існуючого (не працює) контейнера. Це можна зробити наступним чином:

  1. Відкрийте файл конфігурації, що відповідає зупиненому контейнеру, який можна знайти на /var/lib/docker/containers/99d...1fb/config.v2.json (можливо, config.jsonдля старих версій докера).

  2. Знайдіть MountPointsрозділ, який у моєму випадку був порожнім:"MountPoints":{} . Далі замініть вміст чимось подібним (ви можете скопіювати належний вміст з іншого контейнера з належними налаштуваннями):

"MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}

або те саме (відформатовано):

  "MountPoints": {
    "/mnt": {
      "Source": "/home/<user-name>",
      "Destination": "/mnt",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/home/<user-name>",
        "Target": "/mnt"
      },
      "SkipMountpointCreation": false
    }
  }
  1. Перезапустіть службу докера: service docker restart

Це працює для мене з Ubuntu 18.04.1 та Docker 18.09.0


3
Дякую за відповідь. Крок 3 має вирішальне значення. Я також додам, що краще спочатку зупинити контейнер докер, перш ніж робити запис.
buzypi

7
Це найкраща відповідь, оскільки він повністю зберігає існуючий контейнер. Це те, що я зробив: 1. Зупиніть механізм докера: systemctl stop docker.service2. Редагувати config.v2.json: vim <(jq . /var/lib/docker/containers/<container-ID>/config.v2.json)3. Зберегти оновлення до файлу: :w config.v2.json4. Вийти з vim: :q!5. Оновити наявний файл: jq -c . config.v2.json > /var/lib/docker/containers/<container-ID>/config.v2.json6. Запустити докер-механізм: systemctl start docker.service7. Запустити контейнер, якщо потрібно : docker start <container-name/ID>8. Насолоджуйтесь :-)
Android Control

2
Ключовим кроком є service docker restart. Я спробував, щоб docker restart <container>потім нова конфігурація не була вибрана, і вона буде перезаписана старою конфігурацією.
KFL

1
Також jqдопоможе досить надрукувати JSON , так це mroe люди редагованого:cat config.v2.json | jq . > config.json
KFL

14

Jérôme Petazzoni має досить цікавий пост у блозі про те, як додати об'єм до контейнера, поки він працює . Це не те, що вбудовано в Докер поза коробкою, але можливо здійснити.

Як він також вказує

Це не працюватиме у файлових системах, які не базуються на блокових пристроях.

Він буде працювати лише в тому випадку, коли / proc / mounts правильно перелічить вузол блокового пристрою (що, як ми бачили вище, не обов'язково відповідає дійсності).

Крім того, я тестував це лише в моєму місцевому середовищі; Я навіть не приміряв хмарний екземпляр чи щось подібне

YMMV


8

На жаль, опція перемикання для монтажу гучності є лише в runкоманді.

docker run --help

-v, --volume list Bind mount a volume (default [])

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

  1. Експортуйте свій контейнер docker container export -o ./myimage.docker mycontainer
  2. Імпортувати як зображення docker import ./myimage.docker myimage
  3. Тоді docker run -i -t -v /somedir --name mycontainer myimage /bin/bash

1
FYI - docker containerне допустима команда 1.11.2 (це остання версія, яка підтримується Synology на цей час). Я не можу знайти жодного документа, який би сказав, коли він був доданий. У цьому випадку перша команда docker export -o ./myimage.docker mycontainer.
Кріс Р. Доннеллі

2

Примітка про використання контейнерів Docker Windows після того, як мені довелося довго шукати цю проблему!

Умови:

  • Windows 10
  • Docker Desktop (остання версія)
  • використання Docker Windows Container для малюнка microsoft / mssql-server-windows-developer

Проблема:

  • Я хотів встановити хост-словник у свій контейнер Windows.

Рішення, як частково описано тут:

  • створити контейнер докера

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

  • перейти до командної оболонки в контейнері

docker exec -it <CONTAINERID> cmd.exe

  • створити DIR

mkdir DirForMount

  • стоп-контейнер

docker container stop <CONTAINERID>

  • здійснити контейнер

docker commit <CONTAINERID> <NEWIMAGENAME>

  • видалити старий контейнер

docker container rm <CONTAINERID>

  • створити новий контейнер з новим зображенням та монтажем гучності

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>

Після цього я вирішив цю проблему на контейнерах докер Windows.


-3

Найкращий спосіб - скопіювати всі файли та папки всередині каталогу у вашій локальній файловій системі: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

SRC_PATH знаходиться на контейнері DEST_PATH знаходиться на localhost

Тоді робіть docker-compose down додайте гучність до тієї жDEST_PATH та запустіть Docker-контейнери за допомогоюdocker-compose up -d

Додайте гучність, дотримуючись в docker-compose.yml

volumes:
 - DEST_PATH:SRC_PATH

Вище є інші, кращі варіанти.
Пан

Дійсно, вище є варіанти, і копіювання файлів навколо них не встановлюється. Крім того, визначення "томів", що надається для опції докер-композиції, є навпаки: томи: - HOST_PATH: CONTAINER_PATH
Гійом С.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.