docker быстрый старт - Как работать с постоянным хранилищем (например, базами данных) в Docker




7 Answers

Докер 1.9.0 и выше

Использовать API объема

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command

Это означает, что шаблон контейнера только для данных должен быть оставлен в пользу новых томов.

Фактически API-интерфейс тома - это только лучший способ добиться того, что было шаблоном данных-контейнера.

Если вы создаете контейнер с -v volume_name:/container/fs/path Docker автоматически создаст именованный том для вас, который может:

  1. Перечисляться через docker volume ls
  2. docker volume inspect volume_name
  3. Резервное копирование как обычный каталог
  4. Резервное копирование по-прежнему через --volumes-from connection

Новый API томов добавляет полезную команду, которая позволяет идентифицировать оборванные тома:

docker volume ls -f dangling=true

И затем удалите его через свое имя:

docker volume rm <volume name>

Как подчеркивает @mpugach в комментариях, вы можете избавиться от всех оборванных томов с помощью приятного однострочного интерфейса:

docker volume rm $(docker volume ls -f dangling=true -q)
# Or using 1.13.x
docker volume prune

Докер 1.8.x и ниже

Подход, который, как представляется, лучше всего подходит для производства, заключается в использовании контейнера только для данных .

Контейнер только для данных запускается на изображении с баребонами и фактически ничего не делает, кроме раскрытия тома данных.

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

docker run --volumes-from data-container some-other-container command-to-execute
  • Here вы можете получить хорошее представление о том, как организовать различные контейнеры.
  • Here есть хорошее представление о том, как работают тома.

В этом сообщении в блоге есть хорошее описание так называемого контейнера как шаблон тома, который поясняет основной смысл наличия только контейнеров данных .

Документация Docker теперь имеет ОПРЕДЕЛЕННОЕ описание контейнера как шаблон объема / с .

Ниже приведена процедура резервного копирования / восстановления для Docker 1.8.x и ниже.

РЕЗЕРВНОЕ КОПИРОВАНИЕ:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
  • --rm: удалить контейнер, когда он выйдет
  • --volumes-from DATA: присоединяться к томам, разделяемым контейнером DATA
  • -v $ (pwd): / backup: привязать текущий каталог к ​​контейнеру; написать tar-файл в
  • busybox: небольшое упрощенное изображение - полезно для быстрого обслуживания
  • tar cvf /backup/backup.tar / data: создает несжатый файл tar всех файлов в каталоге / data

ВОССТАНОВИТЬ:

# Create a new data container
$ sudo docker run -v /data -name DATA2 busybox true
# untar the backup files into the new container᾿s data volume
$ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
data/
data/sven.txt
# Compare to the original container
$ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data
sven.txt

Вот хорошая статья от превосходного Брайана Гоффа, объясняющего, почему хорошо использовать одно и то же изображение для контейнера и контейнера данных.

обучение dockerfile

Как люди справляются с постоянным хранением ваших контейнеров Docker?

В настоящее время я использую этот подход: создайте образ, например, для PostgreSQL, а затем запустите контейнер с помощью

docker run --volumes-from c0dbc34fd631 -d app_name/postgres

ИМХО, у которого есть недостаток, что я никогда не должен (случайно) удалять контейнер «c0dbc34fd631».

Другая идея заключалась бы в том, чтобы монтировать тома хоста «-v» в контейнер, однако идентификатор пользователя в контейнере не обязательно совпадает с идентификатором пользователя с хоста, а затем разрешения могут быть испорчены.

Примечание. Вместо --volumes-from 'cryptic_id' вы также можете использовать --volumes-from my-data-container где my-data-container - это имя, которое вы назначили контейнеру только для данных, например, docker run --name my-data-container ... (см. принятый ответ)




Начиная с Docker Compose 1.6, теперь улучшена поддержка объемов данных в Docker Compose. Следующий файл компоновки создаст образ данных, который будет сохраняться между перезапусками (или даже удалением) родительских контейнеров:

Вот объявление в блоге: Compose 1.6: Новый файл Compose для определения сетей и томов

Вот пример создания файла:

version: "2"

services:
  db:
    restart: on-failure:10
    image: postgres:9.4
    volumes:
      - "db-data:/var/lib/postgresql/data"
  web:
    restart: on-failure:10
    build: .
    command: gunicorn mypythonapp.wsgi:application -b :8000 --reload
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

volumes:
  db-data:

Насколько я понимаю: это создаст контейнер объема данных ( db_data ), который будет сохраняться между перезапусками.

Если вы запустите: docker volume ls вы должны увидеть свой том в списке:

local               mypthonapp_db-data
...

Вы можете получить более подробную информацию об объеме данных:

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]

Некоторые тесты:

# Start the containers
docker-compose up -d

# .. input some data into the database
docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py createsuperuser
...

# Stop and remove the containers:
docker-compose stop
docker-compose rm -f

# Start it back up again
docker-compose up -d

# Verify the data is still there
...
(it is)

# Stop and remove with the -v (volumes) tag:

docker-compose stop
docker=compose rm -f -v

# Up again ..
docker-compose up -d

# Check the data is still there:
...
(it is).

Заметки:

  • Вы также можете указать различные драйверы в блоке volumes . Например, вы можете указать драйвер Flocker для db_data:

    volumes:
      db-data:
        driver: flocker
    
  • Поскольку они улучшают интеграцию между Docker Swarm и Docker Compose (и, возможно, начинают интегрировать Flocker в экосистему Docker (я слышал слухи, что Docker купил Flocker), я думаю, что этот подход должен стать все более мощным.

Отказ от ответственности: этот подход является многообещающим, и я успешно использую его в среде разработки. Я бы боялся использовать это в производстве еще!




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

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




Ответ @ tommasop является хорошим и объясняет некоторые из механизмов использования контейнеров только для данных. Но как тот, кто изначально считал, что контейнеры данных глупы, когда можно просто привязать монтирование к хосту (как это было предложено несколькими другими ответами), но теперь понимает, что на самом деле контейнеры только для данных довольно аккуратные, я могу предложить свои собственные сообщение в блоге по этой теме: Почему Docker Data Containers (тома!) хороши

См. Также: мой ответ на вопрос « Каков наилучший способ управления разрешениями для разделяемых томов Docker? » На примере использования контейнеров данных для предотвращения таких проблем, как разрешения и сопоставление uid / gid с хостом.

Чтобы обратиться к одной из первоначальных проблем OP: чтобы контейнер данных не удалялся. Даже если контейнер данных удален, сами данные не будут потеряны, если любой контейнер имеет ссылку на этот том, т.е. любой контейнер, который установил том через --volumes-from . Поэтому, если все связанные контейнеры не будут остановлены и удалены (можно считать это эквивалентом случайного rm -fr / ), данные безопасны. Вы всегда можете воссоздать контейнер данных, выполнив --volumes-from любого контейнера, который имеет ссылку на этот том.

Как всегда, делайте резервные копии!

ОБНОВЛЕНИЕ: теперь у Docker есть тома, которые можно управлять независимо от контейнеров, что дополнительно упрощает управление.




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

  • Храните его на хосте
    • Используйте флаг -v host-path:container-path для сохранения данных каталога контейнера в каталог хоста.
    • Резервное копирование / восстановление происходит путем запуска контейнера резервного копирования / восстановления (например, tutumcloud / dockup), установленного в тот же каталог.
  • Создайте контейнер данных и установите его тома в контейнер приложения.
    • Создайте контейнер, который экспортирует том данных, используйте --volumes-from для монтирования этих данных в свой контейнер приложения.
    • Резервное копирование / восстановление аналогично описанному выше решению.
  • Используйте плагин Docker volume, который поддерживает внешнюю / стороннюю службу
    • Плагины объема докеров позволяют вашему источнику данных поступать откуда угодно - NFS, AWS (S3, EFS и EBS)
    • В зависимости от плагина / сервиса вы можете присоединить один или несколько контейнеров к одному тому.
    • В зависимости от службы резервное копирование / восстановление могут быть автоматизированы для вас.
    • Хотя это может быть громоздким делать вручную, некоторые решения оркестровки - например, Rancher - запекли и просты в использовании.
    • Convoy - это самое простое решение для этого вручную.



Недавно я написал о потенциальном решении и приложении, демонстрирующем технику. Я считаю, что он очень эффективен во время разработки и производства. Надеюсь, это поможет или искромет некоторые идеи.

Repo: https://github.com/LevInteractive/docker-nodejs-example
Статья: http://lev-interactive.com/2015/03/30/docker-load-balanced-mongodb-persistence/




Мое решение состоит в том, чтобы использовать новый docker cp , который теперь может копировать данные из контейнеров, неважно, работает ли он или нет, и совместно использовать хост-тома в то же самое место, где приложение базы данных создает свои файлы базы данных внутри контейнер. Это двойное решение работает без контейнера только для данных, прямо из исходного контейнера базы данных.

Поэтому мой сценарий initd systemd выполняет резервное копирование базы данных в архив на хосте. Я поместил временную метку в имени файла, чтобы никогда не переписывать файл.

Это делается на ExecStartPre:

ExecStartPre=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStartPre=-/bin/bash -c '/usr/bin/tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStartPre.tar.gz /home/core/sql/mysql --remove-files'

И он тоже делает то же самое на ExecStopPost:

ExecStopPost=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStopPost=-/bin/bash -c 'tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStopPost.tar.gz /home/core/sql/mysql --remove-files'

Кроме того, я обнаружил папку с хоста как тома в том же месте, где хранится база данных:

mariadb:
  build: ./mariadb
  volumes:
    - $HOME/server/mysql/:/var/lib/mysql/:rw

Он отлично работает на моей виртуальной машине (я создаю для себя LEMP-стек): https://github.com/DJviolin/LEMP

Но я просто не знаю, является ли это «пуленепробиваемым» решением, когда ваша жизнь зависит от него (например, интернет-магазин с транзакциями в любых возможных милисекундах)?

В 20 мин. 20 секунд от этого официального видеозаписей Docker ведущий делает то же самое с базой данных:

Начало работы с Docker

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




Related