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

image

Давайте без промедления запустим базу данных PostgreSQL в контейнере Docker!

Чтобы у вас получились все шаги, описанные ниже, у вас на ПК должен быть установлен Docker. О том, как это делается в самых популярных ОС, даны здесь: Ubuntu, Windows, Mac.

Для быстрого старта откройте командную строку и выполните команду:

$ docker run --name postgres-docker -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres

Вот в чём её суть:
  • Она подтягивает Docker-образ postgres из Docker Hub,
  • устанавливает переменную окружения POSTGRES_PASSWORD в значение postgres,
  • называет (--name) контейнер Docker вот так: postgres-docker ,
  • отображает внутренний порт 5432 этого контейнера на внешний порт 5432, так, что появляется возможность зайти в этот контейнер извне,
  • после чего позволяет нам выполнять контейнер Docker в фоновом режиме (-d).

Итак, если теперь вы хотите зайти в базу данных через какое-нибудь приложение с графическим пользовательским интерфейсом (GUI) – например, pgAdmin, Adminer, т.д.), у вас это должно получиться.

Я предпочитаю пользоваться DBeaver, но вы можете работать с тем инструментом, который нравится вам больше всего. Итак, чтобы подключиться к базе данных из приложения, нужно указать параметры соединения (большинство из них задаются по умолчанию в образе Docker). Полное резюме по ним приводится на следующем скриншоте из DBeaver:

image

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

image

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

Нет ничего проще, всего лишь введите в командной строке следующий код:

$ docker exec -it postgres-docker bash

При помощи exec мы заходим в образ postgres-docker в открепленном режиме -it и приступаем к работе с его bash-приложением (bash).

Так мы попадаем в командную строку контейнера Docker – и поэтому можем войти в базу данных как пользователь postgres.

root@377ef2b9b13e:/# psql -U postgres

psql (11.4 (Debian 11.4-1.pgdg90+1))
Type "help" for help.
postgres=#

Здесь мы можем делать всё, что нам захочется: создавать новые базы данных, новые таблицы, наполнять их данными и т.д. Например, можно создать простую таблицу:

postgres=# CREATE TABLE public.persons (id int PRIMARY KEY, lastName varchar(255), firstName varchar(255), address varchar(255));

Но теперь логичен вопрос: а можно ли автоматизировать создание базы данных? В особенности, если речь идёт о сложной базе данных, содержащей множество таблиц? Ответ: да, конечно!

Создаём наш собственный образ PostgreSQL Docker на основе Dockerfile


Чтобы решить эту задачу, нам потребуется создать наш собственный образ postgres Docker. Это модно сделать на основе Dockerfile – текстового документа, используемого в Docker для сборки пользовательского образа.

FROM postgres 
ENV POSTGRES_PASSWORD postgres 
ENV POSTGRES_DB testdb 
COPY init.sql /docker-entrypoint-initdb.d/

Вышеприведённая инструкция состоит из четырёх шагов, а именно:
  • Первым делом мы приказываем Docker подтянуть образ postgres (этот шаг уже был рассмотрен выше),
  • Затем устанавливаем значения для двух переменных окружения (ENV): POSTGRES_PASSWORD и POSTGRES_DB – соответственно postgres и testdb (список всех переменных, доступных в данном образе, можно найти в Docker Hub),
  • и, наконец, копируем (COPY) файл init.sql, расположенный в том же каталоге, что и Dockerfile, в каталог /docker-entrypoint-initdb.d/, находящийся в используемом нами postgres-образе Docker. По умолчанию все скрипты, находящиеся в этом каталоге, будут автоматически выполняться в ходе пуска контейнера.

Последнее, что нам остаётся сделать – создать вышеупомянутый файл init.sql и положить туда все SQL-скрипты. В моём случае речь о единственном скрипте для создания таблицы:

CREATE TABLE public.persons (
    id int PRIMARY KEY,
    firstName varchar(255),
    lastName varchar(255),
    address varchar(255)
);

Теперь у нас подготовлены два файла (Dockerfile и init.sql), на основе которых мы можем собрать наш собственный образ Docker. Чтобы это сделать, откроем окно терминала в том каталоге, где находятся эти файлы, и выполним команду:

$ docker build -t my-postgres-image .

Sending build context to Docker daemon  62.46kB
Step 1/4 : FROM postgres
 ---> 79db2bf18b4a
Step 2/4 : ENV POSTGRES_PASSWORD postgres
 ---> Running in 0e9f8331845e
Removing intermediate container 0e9f8331845e
 ---> 01fb59dfd17f
Step 3/4 : ENV POSTGRES_DB testdb
 ---> Running in 2d424d207e71
Removing intermediate container 2d424d207e71
 ---> 2139195ef615
Step 4/4 : COPY init.sql /docker-entrypoint-initdb.d/
 ---> d627b332ac02
Successfully built d627b332ac02
Successfully tagged my-postgres-image:latest

В принципе, вышеприведённая команда приказывает Docker собрать из Dockerfile образ под названием my-postgres. Для проверки можете ввести:

$ docker images -aREPOSITORY          TAG     IMAGE ID      CREATED               
my-postgres-image   latest  d627b332ac02  About a minute ago  

Отлично! Теперь давайте запустим всё это как контейнер:

$ docker run -d --name my-postgres-container -p 5555:5432 my-postgres-image

Подключившись к базе данных следующим способом (пароль — postgres):

image

Вы должны получить новую базу данных, в которой уже определена таблица persons:

image

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

INSERT INTO public.persons 
    (id, firstname, lastname, address)
VALUES
    (1, 'Luke', 'Skywalker', 'Tatooine'),
    (2, 'Leia', 'Organa', 'Alderaan'),
    (3, 'Han', 'Solo', 'Corellia');

Затем вернитесь в строку терминала и остановите контейнер при помощи:

$ docker stop my-postgres-container
my-postgres-container

Далее перезапустите контейнер при помощи следующей команды:

$ docker container start my-postgres-container

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

image

Окей… но что было бы, если бы для перезапуска контейнера мы воспользовались командой docker run (как в первый раз), а не docker container start?

Команда docker run создаёт новый контейнер из образа my-postgres-image, так что все изменения, внесённые в my-postgres-container, в новом контейнере не сохраняются.

Следует ли пробовать в продакшене базу данных, положенную в Docker?


Да, но вы уверены, что ваши данные долговременно сохранены? Можем ли мы с сегодняшнего дня переместить в контейнеры Docker все базы данных, расположенные на продакшен-серверах/в продакшен-облаках?

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

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

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

Хорошо, так значит ли это, что контейнеризовать базы данных бессмысленно? Ответить на этот вопрос не так просто. В принципе, если вы выводите ваше решение в продакшен, то не кладите базу данных в Docker. Лучше было бы воспользоваться базой данных как услугой – такой сервис предоставляют многие облачные провайдеры (AWS, GCP, т.д.). Но, если данные не критичны, то есть, если они используются только для разработки или тестирования, то можно обойтись и контейнерами.

Остался один вопрос: как в Docker обеспечивается персистентность данных? Есть три механизма для обеспечения персистентного хранения даннхы в Docker, но я хочу рассказать о наиболее предпочтительном — томах. Если вы хотите подробнее познакомиться с монтированием при помощи bind и tmpfs, то почитайте официальную документацию.

Тома Docker


Тома Docker – это каталоги, расположенные вне контейнера Docker на хост-машине. У контейнеров есть только ссылка на этот путь, и именно в нём они сохраняют всю информацию.

image

Source: docs.docker.com/storage/volumes

Чтобы проверить, какой том присвоен данному контейнеру, выполните следующую команду:

$ docker container inspect my-postgres-container"Mounts": [{

     "Type": "volume",
     "Name": "453e993be5d9f6f863313c3e111e5f53dc65eeb34bff42e5b",
     "Source": "/var/lib/docker/volumes/453e993be5d9f6f863313c3e111e5f53dc65eeb34bff42e5b/_data",
     "Destination": "/var/lib/postgresql/data",
     "Driver": "local",
     "Mode": "",
     "RW": true,
     "Propagation": ""
 }],

Предыдущий листинг – это всего лишь часть файла JSON, выводимого в консоль. В Mounts содержится информация об отображённых каталогах. Параметр Source сообщает, где именно на локальной машине организовано долговременное хранение данных, а Destination указывает местоположение внутри контейнера Docker.

Еще есть параметр Name (имя тома), который по умолчанию присваивает Docker. На самом деле, он плохо поддаётся чтению, но его можно откорректировать.

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

$ docker run -d --name my-postgres-volume -p 7777:5432 -v postgres-volume:/var/lib/postgresql/data my-postgres-image2109993939fdc9fe290c3536bdee09dd4cfba2ff369cf15a17bc841afe0c056f

Единственное, что здесь было добавлено (не считая того, что мы изменили имя контейнера и откорректировали отображение портов) – это новый флаг -v : (или --volume, если предпочитаете), отвечающий за присваивание тома контейнеру Docker.

Теперь, попытавшись проверить (inspect) контейнер, вы должны получить следующую информацию:

$ docker container inspect my-postgres-volume"Mounts": [{
     "Type": "volume",
     "Name": "postgres-volume",
     "Source": "/var/lib/docker/volumes/postgres-volume/_data",
     "Destination": "/var/lib/postgresql/data",
     "Driver": "local",
     "Mode": "z",
     "RW": true,
     "Propagation": ""
}],

Гораздо лучше! Если потребуется узнать информацию о томах, выполните команду:

$ docker volume lsDRIVER         VOLUME NAME
local          453e993be5d9f6f863313c3e111e5f53dc65eeb34bff42e5b
local          postgres-volume

Ещё один способ создать собственный том – воспользоваться этой командой:

$ docker volume create --name my-postgres-volumemy-postgres-volume

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

$ docker run -d --name my-postgres-volume-2 -p 2222:5432 -v my-postgres-volume:/var/lib/postgresql/data my-postgres-image

Ещё одна крутая черта тома такова: его можно одновременно прикреплять к разным контейнерам. Именно так сделано ниже, где мы прикрепляем к новому контейнеру том, уже используемый в настоящий момент.

$ docker run -d --name my-postgres-volume-3 -p 3333:5432 -v my-postgres-volume:/var/lib/postgresql/data my-postgres-image

Теперь, если inspect оба контейнера, то должен получиться точно такой же результат в части Mount файла JSON:

"Mounts": [{
    "Type": "volume",
    "Name": "my-postgres-volume",
    "Source": "/var/lib/docker/volumes/my-postgres-volume/_data",
    "Destination": "/var/lib/postgresql/data",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
}],

Но учитывайте, что у этого решения есть ограничение! Прямо сейчас у нас запущены и работают два контейнера. И, если вы внесёте в любой из них новые данные, например, в my-postgres-volume-2, это ещё не означает, что они будут добавлены и во второй контейнер ( my-postgres-volume-3 )! Обновление второго контейнера (с внесением новых данных) произойдёт только после перезапуска контейнера и возврата в него при помощи этих команд:

$ docker stop container my-postgres-volume-3$ docker start my-postgres-volume-3


Избавляемся от неиспользуемых томов


Последнее, о чём хотелось бы упомянуть – как избавиться от ненужных томов. Их можно удалить один за другим при помощи следующей команды:

$ docker volume rm {volume_name}

Или все сразу:

$ docker volume prune

Вот и всё! Если хотите, можете взять Dockerfile и скрипт SQL у меня в репозитории на GitHub:
wkrzywiec/docker-postgres

Комментарии (39)


  1. KrasPvP
    19.05.2023 13:32
    +10

    FROM postgres

    с таким нужно быть аккуратно и всегда указывать точную версию образа, в ином случае, когда подтянется latest, будет сложно сказать, всё ли заработает ожидаемо


    1. nukhtarov
      19.05.2023 13:32
      +2

      Ну и уязвимый образ может быть


    1. nomhoi
      19.05.2023 13:32
      +1

      Статья ориентирована на разработчиков только начинающих в докер. Разработчики должны уметь накидывать по-быстрому начальные версии докер-файлов, чтобы примерно было понятно, как все должно работать. Дальше посылать их девопсам, админам, для более правильной настройки.
      Разработчикам достаточно изучить https://docs.docker.com/get-started/


      1. programmerjava
        19.05.2023 13:32
        +3

        Хорошо. через пол года или год кто-то пытается повторить туториал и натыкается на то, что пример не работает.

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

        Вы бы смогли облегчить жизнь, добавив всего пару символов - это никак не повышает уровень сложности в данном случае, а наоборот - правильно и не сложно - нужно привыкать


        1. nomhoi
          19.05.2023 13:32

          Да, тоже верно


  1. vagon333
    19.05.2023 13:32

    Замечания:


    1. движок в контейнере, а база во внешнем volume — а зачем?
      Ведь это, как сказано выше, проблема рассинхронизации версий движка и базы.
    2. масштабируемость — если движок в контейнере, то все ресурсы, а зачастую движок пожирает массу памяти на page cache, упираются в ресурсы контейнера. А зачем?
    3. многопользовательский доступ к базе — а зачем такие костыли? Ведь проще хостить базу на сервере базы данных. Тогда и каждый контейнер сможет подключиться к базе через переменные окружения, и с бэкапом базы проще, и с ресурсами легче, и точек отказа (см. п. 1) меньше.
      Но учитывайте, что у этого решения есть ограничение! Прямо сейчас у нас запущены и работают два контейнера. И, если вы внесёте в любой из них новые данные, например, в my-postgres-volume-2, это ещё не означает, что они будут добавлены и во второй контейнер

    База данных — фундамент одного или ряда приложений, процессов трансформации, генерации отчетов. Инфосистема предприятия.
    Т.е. — mission critical component.
    В прод можно откатить код на предыдущую версию, можно поменять веб-дизайн или исправить ошибки UI, можно бизнес логику откатить, но в случае ошибки базу откатить нельзя. В момент озарения что нужен откат, в базе уже новые заказы, оплаты, страховые случаи, кредиты на машины и т.п.


    1. kasthack_phoenix
      19.05.2023 13:32
      +11

      движок в контейнере, а база во внешнем volume — а зачем?

      • Возможность хранить данные нормально, а не кидать всё в оверлеи, которые потом неуправляемы. Дополнительное удобство с tiered storage, когда данные могут быть раскиданы между nvme / sata ssd / hdd.
      • Оттуда же возможность убить / пересоздать контейнер, запуллив версию с тем же тегом, но минорными патчами
      • Бэкапы опять же удобнее делать, когда данные нормально доступны снаружи.

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

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


      1. MaxLevs
        19.05.2023 13:32

        Болле того, если есть уже настроенная система для доставки и разворачивания приложения, нет никаких причин не использовать ту же систему для доставки СУБД. При этом управлять развертыванием можно из того же конфига


    1. nomhoi
      19.05.2023 13:32

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

      Все запросы на изменение БД сохраняются в виде команд и событий на шине сообщений (ну или где-нибудь отдельно, как раз для такого случая). При откате БД команды и события изменяющие записи БД накатываются заново. Паттерн Command.
      Так вообще кто-нибудь делает?


      1. vagon333
        19.05.2023 13:32
        +1

        При откате БД команды и события изменяющие записи БД накатываются заново.
        Паттерн Command.
        Так вообще кто-нибудь делает?

        А в это время компания табанит и всю работу ведет на бумажке.


      1. laatoo
        19.05.2023 13:32

        Все запросы на изменение БД сохраняются в виде команд и событий на шине
        сообщений (ну или где-нибудь отдельно, как раз для такого случая). При
        откате БД команды и события изменяющие записи БД накатываются заново.

        эмм, дамп бд не тот же результат даст?

        ведь это же буквально и есть create table, insert, update, alter table, insert, insert, upfate


    1. AlexGluck
      19.05.2023 13:32
      +1

      1. движок в контейнере, а база во внешнем volume — а зачем?Ведь это, как сказано выше, проблема рассинхронизации версий движка и базы.

      Не используйте оверлеи и в качестве постоянного хранения можно хоть nvme диск отдать.

      1. масштабируемость — если движок в контейнере, то все ресурсы, а зачастую движок пожирает массу памяти на page cache, упираются в ресурсы контейнера. А зачем?

      Доктор, когда я тыкаю себя ножом мне больно.
      Не тыкайте себя ножом.

      Не ограничивайте у контейнера ресурсы и всё будет нормально.

      В общем, всё что вы написали бред и идёт от вашей необразованности о механизмах работы изоляции нейсмпейсов в ядре ОС линукс.


  1. SlavikF
    19.05.2023 13:32
    +1

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

    Плюсов от переноса DB с хоста в докер на самом деле мало:

    • Докер добавляет некоторую изоляцию, но у DB есть встроенная изоляция на уровне пользователей.

    • Управлять версиями через Докер удобнее (можно легко откатиться, поменять), но с DB этого делать как раз нельзя.

    • Бэкапы в Докере делать удобней, но на уровне файловой системы с DB делать нельзя - поэтому вам всё равно надо будет использовать родные dump-утилиты.

    Сегодня контейнеры часто используют для того, чтобы их можно было запускать контейнеры на разных хостах (Docker Swarm, Kubernetes), но вот тут как раз с DB засада - потому что если переносить DB с одного хоста на другой - то возникает вопрос - а где будут храниться данные? Volumes сами по себе не переносятся, NFS для баз данных не очень хорошо подходит, есть iSCSI, но в конце концов - что NFS, что iSCSI - это будет что-то вне Докера, и какой смысл тогда DB движок запихивать в Докер? Тогда уже проще поставить DB туда же, где и storage.

    Вообще вопрос, где запускать DB в контейнеризированных системах - непростой и про это много написано. В данной статье как-то уж слишком примитивно: используйте volumes, и будет вам счастье... Для простенького сайта подойдёт, но есть нужно High Availability, High performance, то всё немного сложнее.


    1. laatoo
      19.05.2023 13:32

      если переносить DB с одного хоста на другой - то возникает вопрос - а где будут храниться данные?

      в актуальном хосте, куда попадут с дампа


    1. aywan
      19.05.2023 13:32

      Используем таким же образом - базу в контейнере, данные на хосте.

      Обновление проще, можно быстро заменить одну версию на другую. Зачем это на бою? Обычно проверяем на "отсоединененой" реплике что все работает как нужно, в рамках минорных обновлений. Можно расскатывать базу на разных окружениях и не зависеть от хоста (rhel, debian), не зависеть от библиотек и также быстро закрывать проблемы в хостовых либах. Ну и главный плюс у разработчиков точно такая же база, также самая версия.

      Минусы: докер накладывает свои ограничения по ресурсам, нужно конфигурировать.


  1. savostin
    19.05.2023 13:32
    +4

    Основной плюс докера (не только для баз) - возможность запустить 2+ контейнера разных версий. Попробуйте запустить на хосте 2 postgres - все не так тривиально.


    1. mc2
      19.05.2023 13:32

      Ну не то что бы очень сложно. Главный вопрос в этом случае как ими управлять.


      1. savostin
        19.05.2023 13:32

        Да, конфиги для каждого прописать свои, пути к данным и не дай бог нужны разные версии каких-нибудь системных либ. Ну и (не)обновлять прикольно.


        1. N-Cube
          19.05.2023 13:32
          +2

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


          1. savostin
            19.05.2023 13:32
            +1

            Имхо с chroot танцев с бубном много больше, чем `docker run`


            1. N-Cube
              19.05.2023 13:32

              Тогда выбора не было :)


            1. randomsimplenumber
              19.05.2023 13:32

              Танцев одинаково. Просто их нужно делать в каждом chroot отдельно, и с переносимостью сложнее.


  1. Hivemaster
    19.05.2023 13:32
    +1

    Следует ли пробовать в продакшене базу данных, положенную в Docker?

    Нет.


    1. Akon32
      19.05.2023 13:32
      +3

      Почему-то все советы не использовать БД в контейнерах относятся году к 2018. Не потеряли ли эти советы актуальность за 5 лет?


      1. OkGoLove
        19.05.2023 13:32
        +2

        Новых аргументов не завезли.


      1. DikSoft
        19.05.2023 13:32
        +5

        Не потеряли ли эти советы актуальность за 5 лет?

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

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


        1. aGGre55or
          19.05.2023 13:32

          Кодер - это программист в машинном коде. Когда молодые разработчики после курсов питона начинают называть себя кодерами, это они так поднимают себе репутацию. Гордого звания программиста им уже недостаточно, потеряло слово былой блеск.

          В остальном с Вами согласен. Аргументы актуальность не потеряли. Данные для реляционной СУБД должны храниться на файловой системе хоста. Данные какой-нибудь NoSQL должны лежать в памяти, но опять же не в слоях docker. Сам зашёл в статью по заголовку: "база данных в контейнере" - лолшто?! Оказывается, всё-таки в Volume. Ну слава яйцам, отлегло... =)

          Потому что БД - это сами данные. А приложение (Oracle, Postgres, MySQL, etc) которое с ними работает называется - СУБД (Система управления базами данных). Но автор написавший заголовок об этом либо не знает, либо забыл.


      1. PavelBelyaev
        19.05.2023 13:32
        +1

        Я mariadb и mysql несколько лет назад пытался в докере развернуть (на линуксе), может сейчас что-то оптимизировали с io, но тогда - может из-за медленного диска было медленней.

        Была у меня тестовая операция для пересчета всего каталога магазина, ну в общем когда нужно очень много всего получить и записать, всякие там ценовые политики и наследование характеристик...

        Ну и условно когда на хосте это делал, то выполнялось примерно на 40-50% быстрее, конечно это всё +/- секунда-две, а на обычных операциях типа открыть страницу вообще доли секунд, но очевидная просадка в докере есть. Не знаю как это тюннинговать, может я что-то не так делаю, пробовал даже приложение в контейнере бд стартануть в виде консольного скрипта.

        Но больше не пытался, есть сервер БД на хосте, есть несколько приложений в докерах которые с ним работают, просадок никаких нет, всё быстро.


        1. Roman2dot0
          19.05.2023 13:32
          +1

          А потом оказалось, что БД в докере писала не на фс хоста, а в overlayfs?


      1. AlexGluck
        19.05.2023 13:32
        +1

        Они и тогда были не актуальны, просто мало людей умело работать с новыми абстракциями. А сейчас просто толпа даунов кричит что бд в докере нельзя, а на вопрос почему ответить не может.


        1. itmind
          19.05.2023 13:32

          В статье СУБД в докере, а не БД. В комментариях выше указано, что БД в докере работает медленно, а смысла делать СУБД в докере нет. Какие есть аргументы за то, что бы БД или СУБД размещать в докере?


          1. AlexGluck
            19.05.2023 13:32

            Я имел ввиду СУБД.
            В комментариях выше заблуждаются.

            Аргументы зачем нужен докер для программы "X" такие же как и для программы "Y":
            * контролируемость
            * повторяемость
            * упрощение обслуживания
            * упрощение эксплуатации

            Даже для СУБД необходимо поставлять обновления для исправления ошибок в коде, улучшения информационной безопасности, добавления нового функционала.

            Ознакомьтесь с докладом крупного маркетплейса, которые 4 года назад рассказывали о 2х летнем опыте продакшен использования СУБД в контейнерах. https://habr.com/ru/articles/527042/

            У меня есть кейс использования СУБД в контейнерах который почти 4 года работает в продакшене одного портала государственного органа.


            1. DikSoft
              19.05.2023 13:32

              Даже для СУБД необходимо поставлять обновления для исправления ошибок в коде, улучшения информационной безопасности, добавления нового функционала.

              Слово "Даже" в этом предложении лишнее. Ещё как нужно!
              А ещё неплохо бы регулярно обновлять и нижележащие слои. В случае виртуализации - ОС гостевой машины, в случае контейнеров - как оно там называется, и на обновление которых любители "всё в контейнер!" забивают просто массово, ибо слшком трудоёмко и хз как оно себя поведёт.


              1. AlexGluck
                19.05.2023 13:32

                Если без оркестратора не используйте гавнодокер, попробуйте подман. Обновление будет выглядеть так `package update podman && systemctl restart container-application`.

                Если есть оркестратор (скорее всего куб) открываем документацию и делаем https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/


            1. N-Cube
              19.05.2023 13:32

              По вашей ссылке используют сотни инстансов постгреса и размеры волюмов (EBS volumes ) у них смешные (1ГБ). Если же у вас один инстанс все доступные ресурсы облачного инстанса занимает, какой смысл в докере? Делаете скрипт инициализации и развертываете сколько нужно инстансов с заданной конфигурацией. Обновлять инстансы стандартными командами дебиана, хоть через версию дистрибутива можно перепрыгнуть (если в продакшене, то не рекомендуется это делать впервые), не то что обновления минорные поставить.


              1. AlexGluck
                19.05.2023 13:32
                +1

                Зачем писать свои скрипты, если код уже есть? Если вы обманываете руководителей занимаясь бессмысленным говнокодерством и пишете код который уже есть, не значит, что другие люди хотят так пахабно относиться к работе.

                Если надо выделить целый инстанс или даже барметал кастомный сервер под субд, ну так кубер позволяет навесить на такие узлы лейблы и по ним будет ориентироваться при деплое и контроле жизненного цикла СУБД.


  1. lrrr11
    19.05.2023 13:32

    мне интересно, зачем вообще люди пишут такие статьи? Целевая аудитория - абсолютные новички, которые по какой-то причине должны нагуглить это вместо официальных доков. Автор сам про себя в профиле пишет "DevOps newbie"... Зачем, просто зачем?


    1. LeetcodeM0nkey
      19.05.2023 13:32

      Зачем, просто зачем?

      Статьи на профильных ресурсах, чтобы потом подороже себя продавать на собесах.


  1. javavitchuk
    19.05.2023 13:32

    Думаю стоит отметить, что создавать свой postgres образ, чтобы просто засунуть туда init.sql скрипты не самая лучшая идея) Потому что там может быть и дамп на 10гб. Лучше как раз таки прокинуть скрипт в /docker-entrypoint-initdb.d/ с помощью описанных томов. А примером создания своего образа стоит показать как добавить поддержку русского языка, что для некоторых бывает проблематично, с чем явно много кто сталкивался.