Как перенести том Docker между хостами?

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

Покопавшись в SO, я нашел старый вопрос ( около 2015 года), в котором говорится, что это невозможно, но, учитывая, что прошло 2 года, я решил спросить еще раз.

На случай, если это поможет, я разрабатываю приложение Flask, которое использует [TinyDB] + локальный диск в качестве хранилища данных — я решил, что мне не нужно ничего более необычного, чем это; это проект, сделанный для обучения на данный момент, поэтому я решил пойти очень легко. Структура проекта такая:

/project_directory
|- /app
   |- __init__.py
   |- ...
|- run.py  # assumes `data/databases/ and data/files/` are present
|- Dockerfile
|- data/
   |- databases/
      |- db1.json
      |- db2.json
   |- files/
      |- file1.pdf
      |- file2.pdf

У меня есть папка data/* внутри моих .dockerignore и .gitignore, так что они не находятся под контролем версий и игнорируются Docker при создании образов.

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

Что я хочу сделать, так это развернуть контейнер на удаленном хосте, но на удаленном хосте должны быть заполнены начальные данные (в идеале это должен быть том, который я использовал локально для максимального удобства); позже, когда на удаленный хост будет добавлено больше данных, я хотел бы иметь возможность вернуть их обратно, чтобы во время разработки я работал с актуальными данными, которые ввели мои конечные пользователи.

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


person ericmjl    schedule 16.08.2017    source источник
comment
Это может быть полезно guidodiepen.nl/2016. /05/   -  person yamenk    schedule 16.08.2017


Ответы (2)


Я бы подошел к этому, создав контейнер Docker, в котором хранится копия данных, которыми вы хотите заполнить свою среду разработки. Затем вы можете представить данные в этом контейнере как том и, наконец, смонтировать этот том в свои контейнеры для разработки. Я продемонстрирую на примере:

Создание контейнера данных

Во-первых, мы просто создадим контейнер Docker, который будет содержать ваши начальные данные и больше ничего. Я бы создал Dockerfile в ~/data/Dockerfile и дал ему следующее содержимое:

FROM alpine:3.4
ADD . /data
VOLUME /data
CMD /bin/true

Затем вы можете построить это с помощью:

docker build -t myproject/my-seed-data .

Это создаст образ Docker с тегом myproject/my-seed-data:latest. Образ просто содержит все данные, которыми вы хотите заполнить среду, хранящиеся в /data в образе. Всякий раз, когда мы создаем экземпляр образа в качестве контейнера, он будет предоставлять все файлы в пределах /data как том.

Монтирование тома в другой контейнер Docker

Я предполагаю, что вы запускаете свой контейнер Docker примерно так:

docker run -d -v $(pwd)/data:/data your-container-image <start_up_command>

Теперь вы можете расширить это, чтобы сделать следующее:

docker run -d --name seed-data myproject/my-seed-data
docker run -d --volumes-from seed-data your-container-image <start_up_command>

Здесь мы сначала создаем экземпляр контейнера начальных данных. Затем мы создаем экземпляр контейнера разработки и монтируем в него тома из контейнера данных. Это означает, что вы получите начальные данные по адресу /data в контейнере для разработки.

Это немного утомительно, потому что, как вы знаете, нужно запустить две команды, поэтому мы могли бы пойти дальше и немного лучше организовать это с помощью чего-то вроде Docker Compose.

Простая оркестровка с помощью Docker Compose

Docker Compose — это способ запуска нескольких контейнеров одновременно. Вы можете объявить, как должна выглядеть ваша среда, и сделать такие вещи, как определение:

«Мой контейнер разработки зависит от экземпляра контейнера исходных данных»

Вы создаете файл docker-compose.yml для макета того, что вам нужно. Это будет выглядеть примерно так:

version: 2
services:
  seed-data:
   image: myproject/my-seed-data:latest

  my_app:
    build: .
    volumes_from:
     - seed-data
    depends_on:
     - seed-data

Затем вы можете запустить все контейнеры одновременно, используя docker-compose up -d my_app. Docker Compose достаточно умен, чтобы сначала запустить экземпляр вашего контейнера данных, а затем, наконец, ваш контейнер приложения.

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

Самый простой способ сделать это — отправить контейнер данных в виде образа в Docker Hub. После создания образа его можно отправить в Docker Hub следующим образом:

docker push myproject/my-seed-data:latest

По своей концепции это очень похоже на отправку коммита Git в удаленный репозиторий, вместо этого в этом случае вы отправляете образ Docker. Однако это означает, что теперь любая среда может извлечь этот образ и использовать содержащиеся в нем данные. Это означает, что вы можете повторно сгенерировать образ данных, когда у вас появятся новые начальные данные, отправить их в Docker Hub под тегом :latest, и при повторном запуске среда разработки будет иметь самые последние данные.

Для меня это способ обмена данными «Docker», который обеспечивает переносимость между средами Docker. Вы также можете делать такие вещи, как создание контейнера данных на регулярной основе заданием в среде CI, такой как Jenkins.

person Rob Blake    schedule 16.08.2017
comment
Это сделало это! Огромное спасибо, @rob-blake! :Д :Д :Д - person ericmjl; 16.08.2017
comment
быстрый дополнительный вопрос, если вы будете достаточно любезны, чтобы помочь: скажем, мои пользователи на моем удаленном хосте добавили новые данные, и я хотел бы вернуть их локально, не выполняя docker commits (я слышал, что это становится некрасиво очень быстро), есть ли способ сделать это? - person ericmjl; 31.08.2017
comment
@ericmjl Ну, вы могли бы, например, docker cp извлечь данные из контейнера, создать другой контейнер данных на основе этих данных, отправить новый контейнер данных в Docker Hub, а затем docker pull локально. Вышеупомянутое может быть написано на ежедневной основе и управляться сервером CI, например. Дженкинс. Есть смысл? - person Rob Blake; 01.09.2017

вы можете использовать этот трюк:

docker run --rm -v <SOURCE_DATA_VOLUME_NAME>:/from alpine ash -c "cd /from ; tar -cf - . " | ssh <TARGET_HOST> 'docker run --rm -i -v <TARGET_DATA_VOLUME_NAME>:/to alpine ash -c "cd /to ; tar -xpvf - " '

дополнительная информация

person hassanzadeh.sd    schedule 04.08.2020