Як розгорнути контейнер для докера та пов’язаний з ним контейнер даних, включаючи вміст?


18

Почну з визнання, що я досить новачок у Докер, і я, можливо, підходжу до цієї проблеми з неправильного набору припущень ... дайте мені знати, чи це так. Я бачив багато дискусій про те, як Docker корисний для розгортання, але немає прикладів того, як це робиться насправді.

Ось як я подумав, що це буде працювати:

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

Основний крок тут - це крок 5, який, на мою думку, дозволить зберегти поточний стан (включаючи вміст файлової системи). Потім ви можете перенести цей стан у сховище та витягнути його з іншого місця, давши вам новий контейнер, який по суті ідентичний оригіналу.

Але це, здається, не працює таким чином. Я вважаю, що або крок 5 не робить те, що я думаю, що це робить, або крок 7 (витягування та запуск зображення) "скидає" контейнер до його початкового стану.

Я зібрав набір з трьох зображень та контейнерів Докера, щоб перевірити це: контейнер даних, письменник, який записує випадкову рядок у файл у контейнері даних кожні 30 с, і зчитувач, який просто echoвидає значення в даних файл контейнера та виходи.

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

Створено с

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

Докерфайл:

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

Докерфайл:

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

Докерфайл:

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 "-----"

Коли я будую та запускаю ці контейнери, вони працюють добре і працюють так, як я очікую:

Зупинка та старт на машині розробки:

  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?

Відповіді:


22

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

Спочатку згадаємо кілька визначень

Докерські зображення

Зображення Docker - це по суті файлова система + метадані. Ви можете перевірити вміст файлової системи об'єднання зображень docker за допомогою docker exportкоманди, а також можете перевірити метадані зображення docker за допомогою docker inspectкоманди.

Обсяги даних

з посібника користувача Docker :

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

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

Контейнери для обсягу даних

Цей спеціальний тип контейнера не має нічого особливого. Вони просто зупинені контейнери, що використовують об'єм даних з єдиною і унікальною метою - принаймні один контейнер, що використовує цей об'єм даних. Пам’ятайте, щойно останній контейнер (запущений або зупинений) з використанням заданого обсягу даних буде видалено, цей об'єм стане недоступним через опцію запуску докера --volumes-from .

Робота з контейнерами обсягу даних

Як створити контейнер для обсягу даних

Зображення, яке використовується для створення контейнера обсягу даних, не має ніякого значення, оскільки такий контейнер може залишатися зупиненим і все ще виконувати своє призначення. Отже, щоб створити контейнер даних, названий datatest_dataдля тома, /datafolderпотрібно лише запустити:

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

Ось baseназва зображення (зручно невелике) і trueце команда, яку ми надаємо лише для того, щоб не бачити, як демон-докер скаржиться на відсутність команди. У будь-якому разі після того, як у вас зупинений контейнер, названий 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

Про вчинення та натискання контейнерів

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

Створення резервного копіювання томів даних

У посібнику користувача docker є чудова стаття про створення резервних копій томів даних .


Хороша стаття про розміщення томів: http://container42.com/2014/11/03/docker-indepth-volumes/


Здається, "зображення, яке використовується для створення контейнера обсягу даних, не має ніякого значення", не зовсім коректно. Просто спробуйте "скретч" зображення, яке дасть вам "exec:" true ": виконавчий файл не знайдено"
tcurdt

Незважаючи на цю помилку, ваш контейнер буде створений, щоб виконати його роль як власника обсягу
Thomasleveil

1
Гм - можливо, варто тоді відкрити питання для цього.
tcurdt

ні, така поведінка очікується, оскільки зображення подряпини - це порожнє зображення, яке так /bin/trueчи інакше не може мати двійкове (чи будь-яке інше)
Thomasleveil

1
Тільки одне. Ви сказали, що "як тільки буде видалено останній контейнер (запущений або зупинений) із заданим томом даних, докер знищить цей об'єм даних з / var / lib / docker / volumes.", Але це насправді не так: просто дивіться: docs.docker.com/userguide/dockervolumes ( Об'єм даних зберігається, навіть якщо сам контейнер видалений. Ви повинні вказати docker rm -vкоманду проти останнього контейнера, щоб також видалити об'єм)
juanra

1

Ви також можете використовувати контейнер даних докер для розгортання коду

Я не знаю, чи це хороша практика, але я це роблю так:

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/

Тепер ви можете натискати на зображення і використовувати томи, від яких і т.д. ...


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

1
На другий погляд, прийнята відповідь говорить про те, що томи (або дані всередині неї) не будуть введені, але ви можете додати дані в контейнер, використовуючи COPYабо ADDстворити том VOLUMEв Dockerfile.
andho
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.