Как развернуть Docker-контейнер и связанный с ним контейнер данных, включая содержимое?

18

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

Вот как я думал, что это будет работать:

  1. создайте контейнер данных для хранения постоянных данных на компьютере A
  2. создайте контейнер приложения, который использует тома из контейнера данных
  3. сделать некоторую работу, потенциально изменяя данные в контейнере данных
  4. остановите контейнер приложения
  5. зафиксировать и пометить контейнер данных
  6. отправить контейнер данных в (частный) репозиторий
  7. потяните и запустите образ из шага 6 на машине B
  8. забрать, где вы остановились на машине B

Ключевым шагом здесь является шаг 5, который, как я думал, сохранит текущее состояние (включая содержимое файловой системы). Затем вы можете передать это состояние в хранилище и извлечь его из другого места, предоставив вам новый контейнер, который по сути идентичен оригиналу.

Но, похоже, это не работает. Я обнаружил, что либо шаг 5 не выполняет то, что я думаю, либо шаг 7 (извлечение и запуск изображения) «сбрасывает» контейнер в его исходное состояние.

Для проверки я собрал набор из трех изображений и контейнеров Docker: контейнер данных, модуль записи, который каждые 30 с записывает случайную строку в файл в контейнере данных, и средство чтения, которое просто echoопределяет значение в данных. контейнерный файл и выходы.

Контейнер данных

Создано с

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder

писатель

Создано с

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done

Этот сценарий записывает случайную строку и дату / время /datafolder/data.txtв контейнер данных.

читатель

Создано с

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

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

Stop & Start на машине разработки:

  1. создать контейнер данных
  2. запустить писателя
  3. запустите ридер немедленно, смотрите «нет данных здесь!» сообщение
  4. подождите немного
  5. запустить читатель, увидеть случайную строку
  6. остановить писателя
  7. перезапустить писателя
  8. запустить читатель, увидеть ту же случайную строку

Но совершение и толкание не делают то, что я ожидаю:

  1. создать контейнер данных
  2. запустить писателя
  3. запустите ридер немедленно, смотрите «нет данных здесь!» сообщение
  4. подождите немного
  5. запустить читатель, увидеть случайную строку
  6. остановить писателя
  7. зафиксировать и пометить контейнер данных docker commit datatest_data myrepository:5000/datatest-data:latest
  8. подтолкнуть к хранилищу
  9. удалить все контейнеры и воссоздать их

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

Может кто-нибудь объяснить, где я здесь не так? Или, в качестве альтернативы, укажите на пример того, как развертывание выполняется с помощью Docker?

Kryten
источник

Ответы:

22

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

Сначала давайте вспомним несколько определений

Изображения Docker

Изображения Docker - это, по сути, объединенная файловая система + метаданные. С помощью команды вы можете проверить содержимое файловой системы объединения образов Docker, а с помощью docker exportкоманды - проверить метаданные образа Docker docker inspect.

Объемы данных

из руководства пользователя Docker :

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

Здесь важно отметить, что данный том (как каталог или файл, содержащий данные) можно использовать повторно только в том случае, если существует хотя бы один докер-контейнер, использующий его. Образы Docker не имеют томов, они имеют только метаданные, которые в конечном итоге сообщают, где тома будут монтироваться в файловой системе объединения. Тома данных не являются частью файловой системы объединения контейнеров, так где они? под /var/lib/docker/volumesна DOCKER хоста ( в то время как контейнеры хранятся под /var/lib/docker/containers).

Контейнеры объема данных

Этот особый тип контейнера не имеет ничего особенного. Это просто остановленные контейнеры, использующие том данных с единственной и единственной целью - иметь хотя бы один контейнер, использующий этот том данных. Помните, что как только последний контейнер (запущенный или остановленный), использующий данный том данных, будет удален, этот том станет недоступным через опцию запуска --volumes-from Docker.

Работа с контейнерами объема данных

Как создать контейнер тома данных

Изображение, используемое для создания контейнера тома данных, не имеет значения, так как такой контейнер может оставаться остановленным и выполнять свое назначение. Поэтому для создания контейнера данных с именем datatest_dataдля тома /datafolderвам нужно всего лишь запустить:

docker run --name datatest_data --volume /datafolder busybox true

Вот baseимя образа (удобно маленькое) и trueкоманда, которую мы предоставляем, чтобы не видеть, что демон docker жалуется на отсутствующую команду. В любом случае после того, как вы назвали остановленный контейнер datatest_dataс единственной целью - разрешить вам достичь этого тома с --volumes-fromпомощью docker runкоманды.

Как читать из контейнера тома данных

Я знаю два способа чтения тома данных: первый - через контейнер. Если вы не можете использовать оболочку в существующем контейнере для доступа к этому объему данных, вы можете запустить новый контейнер с --volumes-fromопцией с единственной целью чтения этих данных.

Например:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

Другой способ - скопировать том из /var/lib/docker/volumesпапки. Вы можете узнать имя тома в этой папке, проверив метаданные одного из контейнеров с помощью тома. Смотрите этот ответ для деталей.

Работа с томами (начиная с Docker 1.9.0)

Как создать том (начиная с Docker 1.9.0)

Docker 1.9.0 представил новую команду, docker volumeкоторая позволяет создавать тома:

docker volume create --name hello

Как читать с тома (начиная с Docker 1.9.0)

Предположим, вы создали раздел с именем helloс docker volume create --name hello, вы можете установить его в контейнер с -vопцией:

docker run -v hello:/data busybox ls /data

О совершении и отправке контейнеров

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

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

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


Хорошая статья о томах: http://container42.com/2014/11/03/docker-indepth-volumes/

Thomasleveil
источник
Кажется, «изображение, используемое для создания контейнера тома данных, не имеет значения» не совсем правильно. Просто попробуйте с «чистым» изображением, которое даст вам «exec:« true »: исполняемый файл не найден»
tcurdt
Несмотря на эту ошибку, ваш контейнер будет создан для выполнения своей роли держателя тома
Thomasleveil
1
Хм - может быть, стоит открыть вопрос для этого тогда.
tcurdt
нет, такое поведение ожидается, поскольку скретч-изображение - это пустое изображение, которое в /bin/trueлюбом случае не может иметь двоичного (или любого другого) изображения
Thomasleveil
1
Только одно. Вы сказали, что «как только последний контейнер (запущенный или остановленный), использующий данный том данных, будет удален, docker уничтожит этот том данных из / var / lib / docker / volume.», Но на самом деле это не так: просто посмотрите: docs.docker.com/userguide/dockervolumes ( Тома данных сохраняются, даже если сам контейнер удален. Вы должны указать docker rm -vкоманду для последнего контейнера, также
удаляющего
1

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

Я не знаю, хорошая ли это практика, но я делаю это так:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

Теперь вы можете выдвинуть свое изображение и использовать объемы от и т.д ...

jmny
источник
Это то, что я ищу, но в принятом ответе прямо говорится, что это невозможно сделать. Сейчас попробую.
andho
1
На второй взгляд, принятый ответ говорит, что тома (или данные внутри него) не будут зафиксированы, но вы можете добавить данные в контейнер с помощью COPYили ADDи создать том с помощью VOLUMEDockerfile.
andho