Как добавить том в существующий контейнер Docker?

У меня есть контейнер Docker, который я создал, просто установив Docker на Ubuntu и выполнив:

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

Я сразу же начал установку Java и некоторых других инструментов, потратил на это некоторое время и остановил контейнер

exit

Затем я захотел добавить том и понял, что это не так просто, как я думал. Если я использую sudo docker -v /somedir run ..., тогда я получаю новый новый контейнер, поэтому я бы установил Java и сделаю то, что я уже сделал, прежде чем просто достать контейнер с установленным томом.

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

Действительно ли это единственный способ добавить том в существующий контейнер?

Ответ 1

Вы можете зафиксировать свой существующий контейнер (то есть создать новое изображение из изменений контейнеров), а затем запустить его с вашими новыми монтируемыми устройствами.

Пример:

$ 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

Если все в порядке, остановите свой старый контейнер и используйте этот новый.

Это оно :)

Ответ 2

Пока да, единственный способ - это отдых. См. Docker Pull Request 8484, когда мы можем ожидать функциональности динамического добавления.

Ответ 3

У нас нет никакого способа добавить том в работающий контейнер, но для достижения этой цели вы можете использовать следующие команды:

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

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Для справки смотрите:

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

Ответ 4

Жером Петаццони имеет довольно интересное сообщение в блоге о том, как Приложить объема в контейнер, пока он работает. Это не то, что встроено в Docker из коробки, но возможно выполнить.

Как он также указывает

Это не будет работать в файловых системах, которые не основаны на блочных устройствах.

Он будет работать только в том случае, если /proc/mounts правильно отображает блок-устройство node (которое, как мы видели выше, не обязательно верно).

Кроме того, я тестировал это только в своей локальной среде; Я даже не пробовал экземпляр облака или что-то в этом роде

YMMV

Ответ 5

Я успешно смонтировал папку /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. Перезапустите службу Docker: service docker restart

Это работает для меня с Ubuntu 18.04.1 и Docker 18.09.0

Ответ 6

К сожалению, опция переключателя для монтирования тома находится только в команде run.

docker run --help

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

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

  • Экспорт контейнера docker container export -o ./myimage.docker mycontainer
  • Импорт как изображение docker import ./myimage.docker myimage
  • Затем docker run -i -t -v /somedir --name mycontainer myimage /bin/bash

Ответ 7

Лучший способ - скопировать все файлы и папки в каталог в вашей локальной файловой системе: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

SRC_PATH находится на контейнере DEST_PATH находится на локальном DEST_PATH

Затем выполните docker-compose down присоедините том к тому же DEST_PATH и запустите Docker-контейнеры, используя docker-compose up -d

Добавьте объем, следуя в docker-compose.yml

volumes:
 - DEST_PATH:SRC_PATH

Ответ 8

Замечание по использованию контейнеров Docker Windows после того, как мне пришлось долго искать эту проблему!

Condiditions:

  • Windows 10
  • Docker Desktop (последняя версия)
  • использование Docker Windows Container для образа microsoft/mssql-server-windows -d eveloper

Проблема:

  • Я хотел смонтировать словарь хоста в мой контейнер 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>

После этого я решил эту проблему на контейнерах Docker Windows.