Pull to refresh

Comments 194

UFO just landed and posted this here
Не надо выполнять в контейнере более одного процесса.

Очень странная идея, может все-таки не больше одного приложения?
Скажем, если приложение запускает несколько процессов (gunicorn, postgres, ..) нельзя запустить его в контейнере?)

Имеется ввиду, что корневой процесс один, дочерних от него сколько угодно.
Например, если приложение работает с бд, то бд это отдельный контейнер.

Эм… а вы сможете запустить в контейнере два корневых процесса?


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

Так тут и говорят, что не надо запускать в контейнере через supervisord приложения, технически это возможно, ни кто не спорит

От задачи зависит, имхо

Мое имхо, что не зависит, если зависит, значит какие то проблемы в архитектуре
Я не очень понимаю в чем задача, запихнуть gitlab(или любой другой проект) со всеми его зависимостями в один контейнер? Такого рода «контейнеры», просто огромны, в них нельзя изменить зависимости тот же mysql на postgres, почему просто не использовать docker-compose

например если я начинающий разработчик мне лучше чтобы "вжух" и работает, менять там mysql на postgres я не собираюсь


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

docker-compose up -d вжух, это не проблема разработчика, это проблема того, кто предоставляет такие решения
docker-compose имеет серьезный недостаток: он плохо моделирует взаимосвязи между сервисами. Т.е. он хорошо моделирует ситуацию, когда один контейнер нужен для запуска другого (например, БД для бекенда), но когда граф зависимостей становится чуточку сложнее (например, появляется отдельная сущность для миграций, предварительной подготовки данных с нормальной обработкой ошибок), то докер-компоуз пасует.
Это все-таки средство для разработки и отладки.
Я не очень понимаю проблемы, подготавливаете контейнер для миграций или с контейнер для подготовки данных, ставите все это в завивисимости и управляете, давайте реальный кейс если возможно
Простой пример. Предположим, что у нас миграции отдельно (вопрос почему так не рассматриваем — вполне возможно, что лучше их как пишет ниже VolCh засовывать в основной контейнер с сервисом). Задача, чтобы стартовали три контейнера последовательно
(1) БД
(2) миграции
(3) сам сервис
На все контейнеры мы можем поставить healtcheck'и. Попробуйте реализовать с минимальным количеством костылей. Можно в самом контейнере с сервисом сделать ожидание пока база доступна и ждать пока версия схемы БД совпадет с ожидаемым сервисом. Запуск сервисов для разработчика должно быть одной командой (ну, или несколькими, но минимальным количеством) Еще желательно сразу учесть, чтобы сервисы потом поехали в куб с минимальными изменениями и имели возможность масштабироваться.

С архитектурной точки зрения — конечно, лучше сразу реализовывать best practice по разработке сервисов с миграциями схем и пр.
Еще желательно сразу учесть, чтобы сервисы потом поехали в куб с минимальными изменениями и имели возможность масштабироваться.


Вы же сами все и объяснили. Не только желательно, но и нужно, чтобы все это поехало в куб с минимальными изменениями. Поэтому варианта «один контейнер всё-всё-всё внутри» просто не существует. Да, в некоторых местах будет непросто, но никто и не обещал, что жизнь будет малиной.

Перед вами стоит вполне реальная проблематика: миграции БД, которые однозначно затем понадобятся в прод-окружении. Т.е. задачу взаимосвязности сервисов на уровне оркестрации решать все равно придется, почему этим не заняться на этапе проектирования/пруф-оф-концепта? Зачем обязательно выносить этот геморрой на этап «у нас все готово, осталось на прод вытащить». Когда на этом этапе вылазят такие вот «О, хоспади, слона-то я и не приметил», это верный признак в корне неверного подхода.
Ну вот определитесь уже, вам «моделировать взаимосвязи», «выращивать граф зависимостей» и т.д., или таки монолитный контейнер «все-что-нужно внутри». Как бы, один контейнер на все совершенно аналогично не решает каких-либо задач масштабирования, зависимостей и прочего. При этом компоуз хотя бы даст возможность отдать ровно ту же базу данных еще одному сервису в пределах окружения или расшарить данные между набором контейнеров, чего монолит сделать не даст.
Повторюсь, что зависит от задачи. В случае гитлаба и хадупа — это удобный способ упаковать без лишних внешних зависимостей решение и отдать какому-нибудь, например, датасаентисту. Для тестовых целей. Никто не предлагает контейнер-монолит тащить в production (хотя допускаю, что такое тоже может понадобиться).

Касательно docker-compose — это вообще отдельная история и он нерелевантен к изначальному вопросу.
Кхм, а какие такие задачи датасайентист будет решать глубоко-локальным гитлабом? Что он там будет тестить?

Заметьте, я, по сути, не возражаю против наличия нескольких взаимосвязанных процессов внутри контейнера. Есть, действительно, кейсы, когда «чистота подхода» не стоит свеч. Но это кейсы, когда «сервис снаружи» действительно накладывает дополнительные затраты на разработку и обкладывание костылями. Тут уже упоминали VPN-ки, сборку метрик и все вот это. Просто postgre — это заведомо не тот случай, который сколько-нибудь проще решить внутри монолитного контейнера, его, как раз, а) проще, б) разумнее иметь снаружи.
Датасайентист (или тестировщик, или кто там еще) не хочет вникать в детали реализации gitlab. Он хочет запустить его и все. Желательно с максимальной инкапсуляцией всех зависимостей и одной командой. Докер образ omnibus решает эту проблему.
Я тоже как администратор хотел бы GitLab потреблять как законченный сервис, а не конструктор из 100500 элементов. И мне глубоко по барабану что у него в кишках — условный Постгрес версии 9 или Постгрес версии 10.
Датасайентист (или тестировщик, или кто там еще) не хочет вникать в детали реализации gitlab. Он хочет запустить его и все. Желательно с максимальной инкапсуляцией всех зависимостей и одной командой.


Датасайентист, тестировщик и прочие человеки, которые хотят «просто запустить, чтобы работало» не отличат, смею вас заверить, «docker start» от «docker-compose up», например, и для них такой подход монопенисуален подходу с «все в один контейнер».

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


А вот вы, как администратор, должны понимать, где зарыта грабля, и почему так не стоит делать. Впрочем, если вы «администратор локалхоста», вопрос можно снять. Но не выдавайте «best practices» локалхоста за «best practices» системного администрирования.
Я как администратор прекрасно знаю, где зарыта грабля и какое решение в каком случае применять и где может бомбануть.
А Вы притягиваете все к каким-то абсолютам, которые к жизни никакого отношения не имеют.
Вот смотрите: у вас есть докер-образ, в который чудесный создатель софта вместе со своей 2-мегабайтной веб-мордой к базе данных впилил постгре. Где может бомбануть, вы понимаете, ок. Какое решение стоит применять в случае, если бомбануло — подскажете?
Нет такой задачи менять mysql на postgres
Каждый раз, когда вы суете базу данных (либо любой иной контент-провайдер) для сервиса в тот же образ, в котором лежит сам сервис, где-то в мире плачет еще один разработчик SOA-архитектуры.
Короче, вообще непонятно, зачем:
1. Дублировать функционал готового контейнера с движком СУБД в свой «большой контейнер».
2. Прибивать сервис гвоздями-сотками к БД на локалхосте.
3. Отказываться заранее от возможности все это масштабировать и отливать структуру всего этого в бронзе.
При том, что все «плюшки» подхода «вжух и завелось» отлично работают в виде тупенького docker-compose.
Как минимум затем, чтобы не заморачиваться межконтейнерными связями, которые в общем случае «почему-то» настроить сложнее, чем межпроцессными связями в рамках одного контейнера/хоста/неймспейса.

Целью контейнеризации приложения может выступать не только и не столько возможность относительного простого горизонтального масштабирования, но и, например, фиксация окружения приложения. Проще говоря, обеспечение очень схожих окружений в средах разработки, тестирования и эксплуатации.
Как минимум затем, чтобы не заморачиваться межконтейнерными связями, которые в общем случае «почему-то» настроить сложнее, чем межпроцессными связями в рамках одного контейнера/хоста/неймспейса.


Вы точно уверены, что имеете понятие о том, что вы говорите?
Вот ЭТО — базовый докерфайл для нормального контейнеризованного постгреса. Вы вот прямо утверждаете, что принести ЭТО в свой контейнер, а потом поддерживать ЭТО в случае надобности изменений — это проще, чем написать docker-compose.yml? На фоне ЭТОГО link: -postgres — сложно?

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


И опять вы, вероятно, хотите видеть слезы ни в чем не повинных авторов подхода. «Схожесть» окружений в средах разработки, тестирования и эксплуатации достигается тем, что во всех этих средах запускаются ОДНИ И ТЕ ЖЕ образы контейнеров, заради этого, собственно, все и затевалось. Зачем писать отдельный образ, который будет «вести себя почти как боевой», если можно просто развернуть копию боевого. Заодно не понадобится аккуратно ручками носить изменения из одного докерфайла в другой, лежащий по соседству.

Не выдавайте, пожалуйста, свои личные фантазии за «полезные практики». Сколько-нибудь полезной практики ношения СУБД в одном контейнере с сервисом не существует в природе.
Вот именно, что для докеризированного постгреса, который должен конфигурироваться и управляться извне контейнера. Новый уровень абстракции порождает новые сложности по низкоуровневому управлению. Формировать docker-compose сложнее чем сделать RUN apt-get install postgresql.

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

Существует и используется. Чаще всего именно для целей разработки и тестирования, грубо говоря, замена вагрантфайла докерфайлом.
Вот именно, что для докеризированного постгреса, который должен конфигурироваться и управляться извне контейнера.


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

Новый уровень абстракции порождает новые сложности по низкоуровневому управлению.


Сейчас открою вам тайну. docker-compose — это не сервис, не подсистема и не что-то уберсложное. Это просто парсер конфигов, который на выходе отдает все вот эти конструкции docker start --дальше-миллион-параметров. Вы можете ровно то же самое сделать руками. Я вам честно говорю, с постгре внутри контейнера вы огребете гораздо больше геморроя, чем от — link: postgre в докер-компоуз файле.

Не везде разворачивается всё из одних образов, более того не везде всё вообще из образов разворачивается.


Не все — это конкретно постгре. Он, обычно, из образов не разворачивается, и нефиг ему внутри них делать, соответственно.

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


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

Как минимум из-за аппаратных различий и версий ядра.


Версии ядра-то тут при чем? Контейнер как таковой строится поверх libc, и контейнер как раз изолирует libc нужной версии, с точностью до ABI. Короче, ядро не при делах, если чо.

Чаще всего именно для целей разработки и тестирования, грубо говоря, замена вагрантфайла докерфайлом.

Замените docker-compose файлом, или оберните соответствующими sh-скриптами, или, например, завертите все в кубере — и будет вам счастье.
Если постгрес должен иметь возможность конфигурироваться и управляться извне контейнера (а так бывает чуть менее, чем всегда, в случае постгреса), его однозначно проще иметь в отдельном контейнере. В конце концов, вы же для разработческих целей его, вроде, хотели иметь. Вполне реален кейс, когда разработчик что-то накосячил, и нужно отключить от постгреса всех клиентов и пошарить у него в кишках ручками. Вот этот кейс вы как собираетесь реализовывать в своем монолитном контейнере? Докерфайл править, или код приложения?

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

Нет, да, нет. Дело в том, что есть техника, при которой образы для разных сред по-разному тегируются. Тестовая — скажем, image_name:test, для uat — image_name:dev, а продовый образ уже называется по-человечески. Также можно разделить образы для дева и прода, просто раскладываю их в разные registry (репозитории). К чему это я — а то что 100% идентичность образов в test/dev/prod и НЕ НУЖНА. Это дополнительный фактор головной боли, который не всегда дает какие-либо профиты. Простой пример — в test/dev легко может монтироваться внутрь контейнера каталог с исходными кодами для оперативного просмотра файловых логов и правки кода «на лету». В prod-контейнере это категорически недоступимо (окей, могу быть менее догматичным, но это не отменяет того, что это будет плохая практика). Далее пример с образами с тестовыми данными — например, образ с Postgres и запеченной внутрь тестовой базой.

Короче, еще раз кратко. Зачастую нет цели делать prod и dev АБСОЛЮТНО идентичными. Эти окружения решают разные задачи и для большинства достаточно определенной степени схожести, которая определяется в каждом случае отдельно.
Если докер инкапсулирован и наружу не светит, то в его кишках априори копаться не надо.


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

Дело в том, что есть техника, при которой образы для разных сред по-разному тегируются. Тестовая — скажем, image_name:test, для uat — image_name:dev, а продовый образ уже называется по-человечески.


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

К тому же в НОРМАЛЬНОЙ практике стремятся к тому, чтобы dev|test|prod образы собирались из одного и того же докерфайла, чтобы не отлаживать еще и их. Если один образ помечен dev, это не значит, что его dockerfile отличается от prod-образа. В нем просто, как правило, лежат разные версии софтины и собирается, возможно, он с разными переменными среды.

Далее пример с образами с тестовыми данными — например, образ с Postgres и запеченной внутрь тестовой базой.

Вот это, в теории, может быть кейсом. При условии, что база либо констрактится на лету из дампа каждый раз при запуске тестов (что сказывается на скорости прохождения этих тестов), либо подмонтирована в read-only, чтобы реран тестов не мог сломать все к чертям. Но это совсем специфический случай, и к «отдать клиенту постгре, упакованный вместе с сервисом» относится мало. Просто клиент за такой подход и проклясть может.

Короче, еще раз кратко. Зачастую нет цели делать prod и dev АБСОЛЮТНО идентичными. Эти окружения решают разные задачи и для большинства достаточно определенной степени схожести, которая определяется в каждом случае отдельно.


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

В разработческом окружении должна быть ровно та же версия glibc, тот же набор установленных пакетов, что и в проде. Элементарно «в лоб» ловите багу:
— на прод окружении мы подключаемся к удаленному серверу postgre (это нормальный подход);
— соответственно сам постгре-сервер на проде не стоит (и это абсолютно правильно);
— в dev-окружение вы для «простоты отладки» постгре-сервер запихали;
— разработчик воткнул в код вызов pgdump перед какой-то «особо опасной» операцией.
Теперь, внимание, вопрос, почему на сервере сервис крашится, а «у разработчика все работает»?

определенной степени схожести, которая определяется в каждом случае отдельно


Вот эта «определенная степень схожести» обычно определяется как «собрано из одного и того же докерфайла». Возможно, с разными ключами сборки, со своими нюансами, но из одного и того же, иначе вся эта мутотень, которую вы затевали с контейнеризацией — зря.
Это у Вас прикол такой демагогию разводить? Какая вообще разница между разными, но похожими Dockerfile или параметризованным (шаблонизированном) Dockerfile с разными путями сборки для dev/prod? Да никакой. Область «похожести» лежит снаружи этого. Поэтому тезис «собрано из одного и того же докерфайла» можно выкинуть.
Несколько постов назад меня пытались убедить, что такие контейнеры хороши в целях отладки и разработки. Т.е. когда в кишках копаться таки надо.

Надо разделить предметную область: «когда нужно копаться в кишках» (и делать соответствующим образом) и «когда не нужно» (например, в случае bundle пакета)
Какая вообще разница между разными, но похожими Dockerfile или параметризованным (шаблонизированном) Dockerfile с разными путями сборки для dev/prod?


Огромная разница: первое — оксюморон и «не надо так делать», второе — ваша личная фантазия. Откуда «параметризованность» и «разные пути сборки» вдруг взялись? Пути — одинаковые, ветки репозитория — разные. Улавливаете?

и «когда не нужно» (например, в случае bundle пакета)


Вот bundle пакет с postgre внутри — ересь.
> Если постгрес должен иметь возможность конфигурироваться и управляться извне контейнера (а так бывает чуть менее, чем всегда, в случае постгреса), его однозначно проще иметь в отдельном контейнере.

Это если должен. Вот официальный образ должен, можно сказать, по определению. А когда какой-то сервис поставляется как локальный для сложной системы и залезание к нему в кишки не рассматривается или вообще прямо запрещено, то логично не использовать конфигурации заточенные под широкие возможности конфигурирования извне. Или другие требования могут быть противоречащие принципу «один контейнер — один процесс» или сильно усложняющие жизнь при его соблюдении. Ну, например, требования доступа к СУБД через файловый сокет, а не сетевой.

> Сейчас открою вам тайну.

Да ладно? А я вам сейчас вообще сорву покровы — докер сам по себе лишь парсер конфигов и команд, манипулирующий средствами ядра типа cgroups. Вы можете ровно то же что делает докер, делать руками.

> Я вам честно говорю, с постгре внутри контейнера вы огребете гораздо больше геморроя, чем от — link: postgre в докер-компоуз файле.

Откуда больше? Постгри в контейнере почти анлогичен постгри на отдельном хосте с точки зрения основного приложения. Сетевое взаимодействие между двумя разными хостами априори сложнее чем в пределах одного хоста. Нет, можно, конечно, «пробивать» изоляцию докера, «прибивать» гвоздями один контейнер к другом, шарить между ними те же файловые сокеты через docker-compose и прочее, но зачем если все проблемы взаимодействия между контейнерами можно решить помещением всего что нужно нашей системе в один контейнер?

> Если у вас приложение для разработчика обернуто в один докерфайл, а в проде — в другой, в вашем монастыре что-то не так с уставом.

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

> Версии ядра-то тут при чем?

Не встречали в документации докера заметок типа «для этой фичи нужно ядро версии не меньше X»?

> Замените docker-compose файлом, или оберните соответствующими sh-скриптами, или, например, завертите все в кубере — и будет вам счастье.

У нас и так есть счастье с одним докер-файлом. Зачем множить сущности сверх необходимого?
Сетевое взаимодействие между двумя разными хостами априори сложнее чем в пределах одного хоста.

Оно не только сложнее, но и дороже в вычислительном плане и медленнее. А еще встает вопрос безопасности в полный рост (этот контейнер мы пускаем внутрь себя, а этот — нет) Я уж не говорю про то, что наши гениальные сетевые инженеры хапнули себе сетку 172.xx.yy.zz, что означает, что по умолчанию докер стартует на ней же и половина корп. сети отваливается. Это решается через daemon.json. Но вот docker-compose чхать хотел на глобальные настройки демона docker'а и пытается сети аллоцировать самостоятельно, что регулярно приводит к проблемам (в результате приходится руками расставлять адреса сетей в docker-compose файлах, либо придумать другие workaround). В этом отношении, конечно, all-in-one (в РАЗУМНОЙ мере) существенно проще и не тянет за собой ворох этих проблем.
Вот да, про конфликты сетей уже подзабыл. Или про требования безопасников, чтобы база по сети не была доступна.
А требования админа, у которого кластер под базы данных поднят, не срать движками субд на каждой второй машинке не в счет?
Выберите молоток и забивайте им гвозди, а не используйте микроскоп. У каждого выбора есть свои резоны и свои trade-off. В случае требований админа — нужно использовать другую дистрибуцию программы (напр., упомянутого выше гитлаба), либо пробрасывать переменные, которые отключат встроенный движок БД (не проверял, но уверен, что они в AIO пакете учли такую потребность).
К тому же необязательно, что «требования админа» по перемещению в БД допустимы (латентность? изоляция данных? Использование каких-то специфических фич какой-то версии движка БД или конфликтующих расширений?)
Т.е. мы сошлись на том, что «бандл» приложения вместе с БД в докер-контейнере — это игрушка для локалхоста, применимая в тех местах, где админа нет, а высоких технологий хочется?
У нас практически наоборот требование было: исходить из того, что две базы всегда на разных хостах, которые по сети друг друга не видят.
Вот я про то и говорю, что именно про базы данных в любом мало-мальски энтерпрайзном окружении есть набор требований. Причем именно требование «носить базу с собой» не встречается нигде, а упаковка БД в контейнер ведет к невыполнимости требования о репликации.
упаковка БД в контейнер ведет к невыполнимости требования о репликации

они ортогональны. В качестве примера могу предложить почитать про операторы кубернетеса, которые реализуют этот функционал для stateful контейнеров типа БД. В случае же докер-контейнеров, которые прибиты гвоздями к конкретным машинам — никаких проблем настроить репликацию нет.
Чтобы операторы кубернетса «реализовывали функционал», нужен stateful-контейнер, отдельный, с БД. БД-на-локалхосте не вканает.

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


В смысле, вы локальную БД, засунутую в контейнер с приложением, без всяких проблем, например в кластер засунете? Или логическую репликацию поднимете на условиях, что слейв мастера не видит? Или фейловер на условиях, что клиент видит только один из серверов? Я что-то не знаю?
Вы строите какие-то допущения, которые сами и опровергаете.
Так неинтересно )
Повторюсь, что если рассматривать докер как средство доставки исполняемых кодов на отдельные машины, то никто не мешает настроить несколько инстансов БД, опубликовать их, например, на внешних портах хостов и связать их репликацией. Что тут такого rocket science в этом?
Зачем так делать? ну, это другой вопрос. Возможно, что Вы хотите изолировать контексты от остальной среды выполнения. Возможно, что хотите «зажать» БД по ресурсам сверху (а не использовать напрямую cgroups). Или что-то еще.
Не-не-не, Девид Блейн! Меня не проведешь, еще раз проверил всю ветку. Я все еще в контексте, вы — выпали.

Мы обсуждаем вариант «поставка приложения вместе со своей postgresql-базой бандлом в одном докер-контейнере». И я утверждаю, что это говно идея, т.к. а) неприменимо в проде, б) неэкономно с точки зрения расхода ресурсов на несколько инстансов приложения, в) становится полным бредом при наличии в организации отдельного сервера БД, г) неконфигурируемо, д) заранее ведет к отказу от репликации, фейловеров БД, возможности использования кластеров.

На фоне этого ваше «никто не мешает настроить несколько инстансов БД, опубликовать их, например, на внешних портах хостов и связать их репликацией» подтверждает, что наличие отдельно стоящих БД — вполне себе нормальная практика, и вы согласны, что оно надо. При этом вы выпали из контекста, и не заметили, что в изначальном контексте фейловеры, кластеры и репликации недоступны, т.к. «только 127.0.0.1, только хардкор», «локалхоста хватит всем» и «настроить — это сложно».

Вот против этого подхода я и протестую. Приложение, тем более вроде ставшего «эталонным» в этом треде gitlab'а от omnibus, рассчитанное на многопользовательскую среду, да еще и с постоянным ростом базы и потенциальным ростом базы клиентов так «пакетить» — говно подход.
Очень ловко смешиваете. :-)
Ваши тезисы:
  • Нельзя засовывать БД (как и любое stateful приложение) в docker-контейнер
  • Нельзя засовывать несколько процессов в один docker-контейнер
  • Как эссенция, объединение предыдущего — нельзя засовывать БД как составной элемент докер-образа типа bundle

Отрицать будете? :-)
Мой тезисы достаточно конкретны:
1. Postgresql (как и все enterprise-level СУБД) — это штука, не предназначенная для того, чтобы ее засовывать в контейнер вместе с приложухой.
2. Отдавать такое в качестве конечного продукта — полное мракобесие.
3. Отмазка «нам так проще» не делает такой подход хорошей практикой.
4. Докерная контейнеризация как таковая ничего не дает в плане управления СУБД.

Можете перечитать целиком ветку, что ли. Я говорил ровно это в контексте ветки. В остальном вы неверно меня истолковали. Возможно, я недостаточно ясно выражался.

К слову подход «сложный граф зависимостей в виде взаимосвязанных процессов в системе» тоже относится к разряду тех самых вещей, которые докер делает не очень хорошо в силу своей специфики. Но это уже тема совершенно отдельного спора.
Спасибо, так разговор предметнее )
1) контейнеры появились раньше чем приложения, предназназначенные для контейнеризации ))
2) как миниум зависит от того, кто целевой пользователь, и есть ли другие варианты поставки
3) Все хорошие практики обычно подразумевают что кому-то проще, сейчас или потом, за счёт других или незаметно для них — детали.
4) упрощает развёртывание новых инстансов по сравнению с традиционными типа «apt install ...»
1) контейнеры появились раньше чем приложения, предназназначенные для контейнеризации ))


Это а) совершенно логично, б) совершенно не повод все в них пихать.

2) как миниум зависит от того, кто целевой пользователь, и есть ли другие варианты поставки


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

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


Еще раз, конкретно этот случай — говно решение, вне зависимости от того, кому проще.

4) упрощает развёртывание новых инстансов по сравнению с традиционными типа «apt install ...»


4.1. Есть масса способов «упростить развертывание новых инстансов». Не нравится apt install — велкам в appImage, snap, flatpak. Задачу доставки приложения призваны решить именно они.
4.2. Загляните в докерфайл. Чем оно лучше apt install, особенно если учитывать тот факт, что внутри там именно apt install + хренова уйма костылей вокруг, чтобы это хоть как-то завелось?
4.3. Чем для пользователя sudo apt install gitlab-ce сложнее docker run gitlab-ce:latest?
4.4. К вопросу о трейд-оффе. Если даже развертывание чем-то проще, вопрос обновления/закрытия уязвимостей начинает «цвести и пахнуть».
1б) Зато это повод не говорить «это приложение не предназначено для контейнеров, поэтому помещать его в окнтейнер мракобесие» ))

2) слишком категорично чтобы быть правдой. А если нас два пользователя всего: я и админ, и бандл собрано и сконфигурирован по по полному обоюдному согласию?

3) аргументы кроме «когда-нибудь пожалеете, когда ресурсов не станет хватать, отказоустойчивость решите сделать и прочие „когда-нибудь“» будут? Я такой бандл даже за технический долг не считаю. Работает, текущим требованиям удовлетворяет, кардинальных изменений не предвидится. И, главное, уже многократно окупил вложенное в него время. Будут новые требования, потребующие разбить всё по «процессам» — хоть с ноля разобьём, хоть на базе существующего. И ничего не потеряем.

4.1) Докер тоже создан для автоматизации развёртывания приложений. Для решения одних и тех же задач часто создаются разные инструменты.

4.2) Там не один apt install, там их много )) Проще разрабатывать и поддерживать, меньше зависит от окружения.

4.3) Меньше вероятность конфликтов при развёртывании как минимум.

4.4) Чем кардинально отличается от apt пакета своего?
1б) Зато это повод не говорить «это приложение не предназначено для контейнеров, поэтому помещать его в окнтейнер мракобесие» ))


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

2) слишком категорично чтобы быть правдой. А если нас два пользователя всего: я и админ, и бандл собрано и сконфигурирован по по полному обоюдному согласию?


То, что вам обоим нравится, не делает это сколько-нибудь нормальной практикой. В виде бандла с базой внутри — оно может приемлемо работать в конкретной комбинации ресурсов, предоставляемых контейнеру на узком use-case'е, подходящим конкретно вам. Дистрибуция в таком виде становится бессмысленной, вариант подпадает под категорию «локальные извращения, которых можно было избежать, но было лень».

3) аргументы кроме «когда-нибудь пожалеете, когда ресурсов не станет хватать, отказоустойчивость решите сделать и прочие „когда-нибудь“» будут? Я такой бандл даже за технический долг не считаю. Работает, текущим требованиям удовлетворяет, кардинальных изменений не предвидится. И, главное, уже многократно окупил вложенное в него время. Будут новые требования, потребующие разбить всё по «процессам» — хоть с ноля разобьём, хоть на базе существующего. И ничего не потеряем.


У вас БД сбандленна внутрь контейнера приложения. Это неиллюзорная возможность потерять, например, историю телодвижений пользователей и начать все «с чистого листа». Вы просто оттянули наступление геморроя. При этом упаковать это в сратый docker-compose — дело получаса. Разгрести эту кашу при миграции — затянется на дни.

4.1) Докер тоже создан для автоматизации развёртывания приложений. Для решения одних и тех же задач часто создаются разные инструменты.


Докер создан заради возможности складывать окружение приложения в тот же репозиторий системы контроля версий, что и само приложение. Короче, вся эта хрень — заради воспроизводимости сборки/окружения. В остальных кейсах есть инструменты лучше.

4.2) Там не один apt install, там их много )) Проще разрабатывать и поддерживать, меньше зависит от окружения.


Разрабатывать и поддерживать ЭТО не проще. При этом воспроизводимость сборки и окружения в этом докерфайле не гарантирована. Докер хорош, действительно хорош для тех случаев, когда ребилд образа не ломает работоспособность приложения. Это не тот случай, тупой ребилд (который может случиться на автомате в любой системе оркестрации) запросто положит рабочий проект. Поэтому в каждой мало-мальски серьезной книжице по докеру/контейнерам приложений/оркестрации контейнерами большими чОрными буквами написано: не кладите ресурс внутрь контейнера, все stateful ресурсы должны подключаться к контейнеру извне. При этом часто рядом стоит пометка на полях для «особо одаренных», что базы данных целиком считаются внешними ресурсами и не должны быть внутри контейнера приложения, если, конечно, террористы не обещают убить вашу сестру в случае, если вы не забандлите ЭТО.

4.3) Меньше вероятность конфликтов при развёртывании как минимум.


Что касается конфликтов при развертывании на локалхосте — взгляните уж на snap и flatpak. Для локалхост-деплоя подходит гораздо лучше, изоляция ровно на тех же механизмах (да-да, все те же cgroups/namespaces), все те же «слои» фс, все то же самое, но плюс некоторое количество умелок, специфичных для локалхоста. Например, в них можно без боли упаковать GUI-приложение, например.

4.4) Чем кардинально отличается от apt пакета своего?


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

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


В виде бандла с базой внутри — оно может приемлемо работать в конкретной комбинации ресурсов, предоставляемых контейнеру на узком use-case'е, подходящим конкретно вам.

Все приложения приемлемо работают в конкретной комбинации ресурсов, все эти минимальные требования, рекомендуемые требования и т. п. об этом. У нас они есть.


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

От того, что мы сделаем два контейнера, один с СУБД, другой с nginx и php-fpm например, особо вероятность не уменьшится.


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

Официальная документация докер гласит иное:
Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly.


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


Разрабатывать и поддерживать ЭТО не проще.

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


не кладите ресурс внутрь контейнера, все stateful ресурсы должны подключаться к контейнеру извне.

А они и подключаютсяя через volume.


Что касается конфликтов при развертывании на локалхосте — взгляните уж на snap и flatpak.

А удаленно они могут "из коробки", без использования средств типа ssh? Ну и основной вопрос: зачем иметь две похожих в чём-то технологии в стэке, если от одной "избавиться" малой кровью не получится? Если нужны средства и уровня "локалхоста" и уровня кластера? Пускай одна немного лучше в случае локалхоста, но кластеры она совсем не умеет.


В том и дело, что ничем.

Не совсем согласен, но если ничем о чём мы вообще разговариваем? Мы не хотим разделять инструменты доставки на локалхостные и кластерные, мы не хотим поддерживать два процесса CI/CD, мы хотим иметь возможность запускать несколько версий системы на одном физическом хосте. Докер нашим хотелкам отвечает.

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


SRSLY? Дефолтная изоляция? Тупой общий бридж с политикой iptables-разреши-все-все-все? Не, я, конечно, согласен, что с такой изоляцией надо бороться. Только не в ту сторону вы боретесь, ее усиливать надо.

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

Все приложения приемлемо работают в конкретной комбинации ресурсов, все эти минимальные требования, рекомендуемые требования и т. п. об этом. У нас они есть.


Дык, вы, получается, собираете конкретный контейнер под конкретную машину. Ну и нафига тут докер-то? Вам виртуализация уровня ОС нужна, например. LXD вам в руки, и никаких знаний там дополнительно не нужно. Запускаете виртуалку, цепляетесь к ней по ssh, рулите из консоли, «как настоящей». Нафига вам простыни докерфайлов?

От того, что мы сделаем два контейнера, один с СУБД, другой с nginx и php-fpm например, особо вероятность не уменьшится.


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

Docker is an open platform for developing, shipping, and running applications.


Developing, shipping and running, чуете.

Developing? В целях разработки — говно подход. Ребилдить весь контейнер вместе с БД при надобности изменения 3 строк в скрипте — говно подход, как разработчик говорю.

Shipping? Доставка приложение на железяку, аналогичную предыдущей? Нафига вы искусственно сокращаете количество target'ов для вашего shipping'а?

Running? Вот строго для «запустить»? Докер НЕ является хорошим инструментом для запуска stateful-приложений. Есть инструменты сильно лучше.

Docker enables you to separate your applications from your infrastructure so you can deliver software quickly.


Вот прямо буквами же написано «to separate your applications from infrastructure». Отделить приложения от инфраструктуры. Забандлить локалхост-онли СУБД = прибить нахрен гвоздями свое приложение к инфраструктуре. СУБД — stateful, по определению, она — ИНФРАСТРУКТУРА. И прямо в «предназначении» докера написано, что он призван ОТДЕЛИТЬ ее от приложения, а не забандлить внутрь.

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


По совокупности умелок работы со stateful-приложениями докер ни по какой совокупности не выигрывает ни у одной платформы оркестрации, и ни у одной системы изоляции уровня ОС.

Банально нежелание иметь зоопарк технологий для одной и той же задачи


Банальное нежелание что-либо изучать, банальное желание вкручивать шурупы молотком, потому что «с молотком мы уже умеем работать (в контексте ваших допущений о докере, конечно, нет, не умеете)», а инструкцию от отвертки еще читать надо.

и конкуренты не относятся к «все знают», а порог входа высок


Порог входа в LXD высок? Относительно порога входа в докер? Забавно, не знал, что 4 страницы текста осилить сложнее, чем 100500-страничный мануал с уточнением нюансов работы и пометками «не носите stateful в контейнере» через абзац.

В те же apt пакеты порог входа выше.


В sudo apt install выше?

Кому как. При разделении одного «локалхоста» на несколько как минимум растёт количество связей между контейнерами, причём растёт в бесконечное число раз: с нуля до минимум одного :)


Поймите уже, вы имеете не «никаких телодвижений» против «оркестрация контейнерами», а «оркестрация процессами» против «оркестрация контейнерами». По сложности примерно монопенисуально, тут соглашусь, если не вдаваться в детали. С той только разницей, что один раз удачно настроенный контейнер вы можете переиспользовать, тупо «заоркестрировав» его в другой неймспейс или в другой сервис. Удачное решение на уровне оркестрации процессами внутри докер-контейнера не переносится, копипаста не в счет.

При том сначала мы используем техглогию изолирующую контейнеры друг от друга


нихрена там не изолируется, о птичках если.

чтобы процессы не заметили, что они изолированы.


Цель докера, как раз, в том, чтобы процесс ЗАМЕТИЛ, что он изолирован. Процесс должен искренне считать, что в пределах системы он один, и тогда все хорошо, и докер тут красавчик. Как только внутри появляется оркестрация процессами, иниты и тому подобное — у докера проблема, хотя бы потому, что инит в докере искренне удивляется, какой такой другой инит вдруг убил его процесс, и на каких, собственно, основаниях.

А они и подключаютсяя через volume.


Подключение СУБД (постреса и ему подобных, не локальной и не ин-мемори) в качестве volume'а — это НЕ «подключение извне», это куцее локалхост-онли извращение.

А удаленно они могут «из коробки», без использования средств типа ssh?


Удаленно что? Установиться? Работать? При чем тут ssh? Какой кейс мы рассматриваем? Собственно, одно могу гарантировать, в контексте LXD любую хотелку, реализуемую в докере, реализовать можно.

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


Зачем иметь отвертку, если есть такой замечательный молоток?

Если нужны средства и уровня «локалхоста» и уровня кластера


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

Пускай одна немного лучше в случае локалхоста, но кластеры она совсем не умеет.


Докер тоже кластеры не умеет, тчк.

Мы не хотим разделять инструменты доставки на локалхостные и кластерные


Реализуемо в 2 вариантах: нефункциональное УГ либо перегруженный комбайн. Короче, не судьба.

мы не хотим поддерживать два процесса CI/CD


Когда вы утверждали, что сбандленная внутрь контейнера база — нормальная вещь для разработки, а для прода можно иметь отдельный докерфайл, два процесса CI/CD вас не смущали. Что изменилось? Когда вы собираете бандл из приложения + движок СУБД, какое отношение это вообще к CI/CD имеет?

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


Кто ж вам запрещает то? Хотите на одном хосте несколько версий ОС — системы виртуализации/изоляции уровня ОС вам в помощь, докер — нет, не в помощь. Хотите запустить несколько версий приложения — тем более в чем проблема, тут можно и докером. Осталось только понять, почему вы несколько версий приложения, каждая со своей БД хотите, а несколько версий/инстансов приложения с общей базой — нет.

Докер нашим хотелкам отвечает.


Да вот нифига.
SRSLY? Дефолтная изоляция?

Ага. ФС контейнеров изолированы, у каждого свой IP в общем случае случайный.


Дык, вы, получается, собираете конкретный контейнер под конкретную машину. Ну и нафига тут докер-то?

Под разные машины с разными дистрибутивами Linux разных версий.


Ну и нафига тут докер-то? Вам виртуализация уровня ОС нужна, например

Забавно, но докер считается именно виртуализацией уровня ОС.


Запускаете виртуалку, цепляетесь к ней по ssh, рулите из консоли, «как настоящей».

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


Нафига вам простыни докерфайлов?

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


Зато появится возможность...

Те возможности, которые нам нужны у нас уже есть.


Ребилдить весь контейнер вместе с БД при надобности изменения 3 строк в скрипте — говно подход, как разработчик говорю.

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


Нафига вы искусственно сокращаете количество target'ов для вашего shipping'а?

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


СУБД — stateful, по определению, она — ИНФРАСТРУКТУРА.

Определение в студию. Оно не под NDA как наши требования? )


а инструкцию от отвертки еще читать надо.

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


Порог входа в LXD высок? Относительно порога входа в докер?

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


В sudo apt install выше?

В dpkg-deb --build и компанию


Какой кейс мы рассматриваем?

Например, собрали образ локально, потестили слегонца и запушили его как-то на сервер QA для текущей ветки, а после апрува — на прод.


Зачем иметь отвертку, если есть такой замечательный молоток?

Поймите, я разработчик и упаковка приложений для меня далеко не основная обязанность. Когда-то собрались все заинтересованные лица, выбрали кадидатов, поигрались с ними и приняли решение что и как будем использовать. Да, может быть выбранный нами молоток в 10% наших случаев проиграет отвёртке с небольшим отставанием, но для нас это приемлемая цена чтобы не разводить зоопарк технологий и тут.


Докер? Средство уровня кластера — это k8s, голым докером вы там не обойдетесь.

Current versions of Docker include swarm mode for natively managing a cluster of Docker Engines.


Собственно начинали когда-то ещё на отдельном Swarm с Consul, потом перешли на встроенный в Докер. k8s для наших задач выглядел как из пушки по воробьям. Да, кстати, наши многопроцессные "бандлы" ближе к подам логически, чем к системам на docker-compose. Не рассматриваем мы сценарии где инстансы СУБД шарятся между разными системами. Одно развёртывание системы — один инстанс СУБД (или один кластер, если считать нескколько инстанс связанных "ручной" репликацией за кластер). Если вся система "помещается" в один контейнер, если процессы СУБД, веб и апп сервера не имеют смысла друг без друга, то не видим смысла их разбивать. Там где видим — разбиваем на десятки контейнеров с десятком инстансов СУБД на одно разворачивание.


а несколько версий/инстансов приложения с общей базой — нет.

Общая база вообще не вариант, поскольку схемы разные могут быть в разных версиях. А общий сервер СУБД — пробовали, плюсом было экономия ресурсов, минусом — конкуренция за ресурсы, одновременное падение всего и вся


Да вот нифига.

Он показал себя много лучше чем apt, bash и ansible.

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

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


«Искусственно увеличить», «дробление одного докер-файла», «добавление докер-композ» — это все не я, например, предлагаю. Я, надеюсь, официальный портал разработчиков докера — достаточно авторитетный источник для поиска «true way» использования докера?

Смотрим конкретно сюда:
Официальный гет-стартед докера от разработчиков.

На всякий случай, если вы неосилятор, кратко изложу суть.

Часть первая: вводная.
Чо такое докер, с чем его едят, для чего он нужен и прочая лабуда, плюс как вкорячить на свою машину докер.

Часть вторая: самый первый контейнер.
Докерфайл, с чем его едят, как собрать и проверить «шевелится ли оно».
Тут можно акцентировать внимание на том факте, что собранный контейнер прямо так и говорит «редис не найден». Рекомендаций положить редис внутрь не видно.

Часть 3: сервисы
О том, как правильно это запускать, крутить и чем собственно само понятие сервиса отличается от контейнера.
Начинается знаменательными словами: "поставьте docker-compose, напишите docker-compose.yml файл.". Это официальная позиция разработчиков докера. Нигде ни разу они не пишут «возьмите голый докер и запустите». Так делать не принято, официальная позиция разработчиков.
Так что композ — это не «лишняя сущность», а официальный «true way» от разрабов самого докера.

Часть 4: Swarm, собираем кластер.
Что такое swarm, как инитить, как запускать, как в него складывать docker-compose файлы.
Замечаем, на всякий случай, что «редис все еще недоступен»

Часть 5: стек.
Что такое стек (группа взаимосвязанных сервисов, делящая между собой определенный набор ресурсов).
Замечаем, что в официальном «хауту» прямо рекомендуют ресурсами рулить на уровне стека, т.е. на уровне оркестрации наборами взаимосвязанных контейнеров. Не в докерфайле. Вот именно здесь редис наконец-то появляется.

Часть 6: деплой.
Как развернуть один и тот же «стек» на разных инстансах от амазон-клауда до локальной машины.

«True way of using Docker (by developers)» — вот это оно. Если вы считаете оркестрацию лишней сущностью… хм, видимо, докеровский get-started вы осилили до 2 части включительно, 3-ю уже не осилили?

Может, приведете мне более авторитетный в области докерной контейнеризации источник, однозначно утверждающий, что бандлить СУБД в контейнер с приложением — это норма?
Для всего свои инструменты. Может у вас сложилось впечатление, что я всё-всё запихиваю в один контейнер? Нет, есть проекты строго соблюдающие принцип один контейнер-один процесс, есть проекты, работающие со внешними базами, есть проекты гибридные (локально базы в контейнерах поднимаются, на проде и стейдже выделенные сервера с репликацией и т. п.), а есть вообще докер не использующие. Я не пихаю один подход везде и всюду, а использую тот, который в данный момент выглядит лучшим по совокупности метрик в среднесрочной перспективе.
Для всего свои инструменты.


Именно. Голый докер, например — для того, чтобы собрать контейнер и проверить сам факт того, что он запускается. Для «запустить его в постоянку» сами разработчики докера предлагают использовать docker-compose, который вы лично неоднократно называли «лишним инструментом, который еще нужно изучать и внедрять». Он не лишний, как выясняется, он — часть «авторского видения» правильного применения докера, и описание его использования является неотъемлемой частью инструкции по применению докера. Просто вы ее не дочитали, что само по себе уже не может являться «best practice».

Вся задумка с докером, из-за чего он, собственно, «взлетел» — это попытка «скрестить ужа с единорогом». Т.е. типично-админские задачи по настройке связности софта перекладываются на традиционно-программерские практики контроля версий. Тут нет никакой «экономии усилий», тут просто происходит сдвиг границ ответственности. Если раньше админ диктовал «окружение» для работы программы, теперь окружение может диктовать разработчик. Только учтите, что необходимость «настройки связности компонент» никуда не девается, просто раньше была цепочка «связность на уровне ОС(админ)» => «связность на уровне приложения (программер)» => «связность на уровне сервиса/окружения (админ)». Вот первую часть дали возможность делать программеру. Нюанс в том, что оно ничего не сэкономило, ни ресурсов, ни денег (дело в том, что программер, в подавляющем количестве случаев, стоит дороже админа).

При этом надо четко осознавать, что «кесарю — кесарево», т.е. есть «обязательная часть программы», которую может реализовывать программер (т.е. собрать что-то, что у него лично запускается и работает), и есть вторая половина — уже непосредственно «доставка на места». И вот вторую программер делать уже не должен, это работа админа. Т.е. программер отдает контейнер с несколькими очевидными «крутилками» для настройки сбоку + docker-compose, который у него лично работает. По docker-compose пролегает «граница ответственности», именно в нем должны содержаться все нюансы реального окружения/твиков системы в целом, все то, что отличает непосредственно девелоперское окружение от рабочего.

Для админа контейнер — черный ящик. Для того и задумывалось, чтобы админ в докерфайл не лез, не его это сфера ответственности, ему докерфайл читать не положено. Он получает продукт в виде готового контейнера. Для него есть эталонный docker-compose.yml локального окружения, это та прослойка, которую должны знать оба, и админ, и разраб. Docker-compose для них — lingva franca.

Собственно, предполагается, что админ, который реально админит postgresql, например, лучше разработчика (который этот постгрес только на локалхосте и видел) знает, как его настроить, как он поведет себя под нагрузкой, и сколько ресурсов ему дать. Т.е. определять настройки СУБД — задача администратора СУБД, зачем разраб в нее вообще лезет? Он все равно сделает это хуже — это раз. Он порождает миллион геморроя для администратора СУБД, который, по изначальной задумке, должен знать конкретно docker-compose.yml формат, и не обязательно должен быть в курсе, что такое вообще этот ваш dockerfile.

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

Это ПЛОХАЯ ПРАКТИКА, так делать не надо. Я не отрицаю, что если разраб + админ сети + администратор СУБД — это одно и то же лицо, можно захренячить все в докерфайл и радоваться жизни, пока все не рухнет к хренам, но это НЕ ЕСТЬ нормальная практика, тем более для продакшена.
Ага. ФС контейнеров изолированы, у каждого свой IP в общем случае случайный.


И зачем вам, простите, прямой доступ к ФС вашей базы данных? А ns-резолвинг на уровне оркестратора не решает проблему «в общем случае случайных ip-адресов»? А возможность средствами оркестрации зафиксировать ip-адрес, чтобы он был не случайным? Вы из пальца не высасываете проблему на ровном месте?

Под разные машины с разными дистрибутивами Linux разных версий.


Повторю, эту проблему можно решить и без докера. При том, что полазить ручками в живой среде, настроить «как надо» проще в отладке, чем «написать докерфайл, который сделает как надо».

Забавно, но докер считается именно виртуализацией уровня ОС.


Загуглите уже, что ли, «контейнер приложения» vs «контейнер ОС». Докер не предполагает наличие внутри полноценного окружения ОС, например. Внутри у него ровно то, чтобы один запущенный процесс считал себя единственным в системе.

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


И чем, собственно, вас «виртуалки» не устроили?
> И зачем вам, простите, прямой доступ к ФС вашей базы данных?

К базе, допустим, не надо. А вот доступ веб-сервера к каталогу upload апп-сервера (ну или наоборот, как смотреть) нужен чуть более чем всегда. И потому часто проще поместить два разных серверных процесса, из которых минимум один полноценный stateful в один контейнер. Да даже без statefull чаще проще поместить их вместе, а не дублировать процесс сборки в разных докерфайлах (ога, копипаста появляется при разбиении), лишь на самом последнем этапе копируя только статику или только приложение в целевой образ.

> А ns-резолвинг на уровне оркестратора не решает проблему «в общем случае случайных ip-адресов»?

Не всё работает через ns.

> А возможность средствами оркестрации зафиксировать ip-адрес, чтобы он был не случайным?

А он, бац, и уже занят.

К базе, допустим, не надо.


Пилять, я вам уже 20 постов подряд говорю: «КОНКРЕТНО К БАЗЕ — НЕ НАДО». Я говорю, дословно: «бандлить СУБД уровня postgres в контейнер с приложением НЕ НАДО, это ПЛОХАЯ ИДЕЯ».

Сам контейнер в момент деплоя предполагается в виде «черной коробки», вы же не собираетесь класть на целевую машину докерфайл и «собирать на месте»? В этой ситуации никакого докерфайла для того, кто деплоит, нет. Есть просто контейнер с какими-то крутилками сбоку, чтобы понастраивать. В таком подходе dockerfile становится частью исходного кода сервиса, а сбандленная внутрь СУБД — это захардкоженный внутрь исходников коннект к базе. Вы же не будете утверждать, что хардкодить пути к файлам, к СУБД, к подключаемым ресурсам в приложении — хорошая практика? Вы же знаете, почему это плохо, и откуда взялось легендарное УМВР?

В случае сборки без контейнера, продукт — это само приложение/бинарник/пакет для развертывания внутри ОС. В случае сборки в контейнере, продукт — это контейнер. И «поправить докерфайл и пересобрать под окружение» — это равносильно «если надо подключиться к другой БД, зайдите в третий сверху файл в папочке app/db/conn в исходниках и пересоберите программу».

А вот доступ веб-сервера к каталогу upload апп-сервера (ну или наоборот, как смотреть) нужен чуть более чем всегда. И потому часто проще поместить два разных серверных процесса, из которых минимум один полноценный stateful в один контейнер.


Ну и в чем, собственно, проблема? Нужен доступ к каталогу? Отлично же, берете один и тот же volume и монтируете его в app-сервер на rw, а веб-серверу в ro. Это «простой случай», и никаких «проблем со сложной настройкой связности». Надо что-то сложнее, чтобы писали оба — подключайте объектное хранилище. Упаковкой обоих процессов в 1 контейнер вы проблему не решите: писать одновременно в 1 файл из двух процессов не менее хреново, чем делать то же самое из двух контейнеров, тем более, что «два контейнера» с точки зрения реальной ФС от двух процессов ничем не различаются, да и не только с точки зрения ФС. Это просто ПО ФАКТУ два локальных процесса.

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


И ЭТИ ЛЮДИ рассказывали мне про «слои» докер-образа? Общую часть — в один докерфайл, различия — каждый в свой, с указанием FROM: общаяЧасть. Не высасывайте проблему из пальца.

Не всё работает через ns.


База данных — работает. Подключение volume'ов — ортогонально проблеме. Что конкретно не работает?

А он, бац, и уже занят.


Кем, простите? Вот вы взяли оркестратор, сказали ему «вот в этот стек отдаем подсетку с набором адресов с xxx.xxx.xxx.1 по xxx.xxx.xxx.200». Внимание, вопрос: кто занял xxx.xxx.xxx.50?
Для описания окружения текстом, который можно хранить в репе приложения и воспроизводить на (почти) любой машине.


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

Альтернатива докеру в этом смысле — баш скрипты провижна и деплоя, ну и ансибли с паппетами как их развитие, а не образы виртуалок. Докер проще и удобнее всего из этого.


Какбы, сильно не во всем проще. И применимость у него сильно Уже.
Ну как разработчик часто ребилдящий контейнеры может вы слышали о практике помещения работы с часто изменяющихся вещей в докерфайле пониже, а редко — повыше, т. к. у докера есть кэширование слоёв.


Как крупный специалист в структуре докер-контейнеров вы, вероятно, в курсе, что нельзя заменить содержимое нижнего слоя без ребилда верхнего? Т.е. при тупом обновлении часовых поясов вы можете нарваться на обновления версии БД поверж живой базы. При протухании кеша во время ребилда докерфайла вы можете нарваться ровно на то же самое. Понимаете, принятая политика в отношении воркеров/фронтендов/интерфейсов и прочего — «release often». В отношении СУБД — не трогать без надобности, обновлять только в том случае, если есть реальная причина это делать, предварительно протестировать жизнеспособность решения. А вы все в один контейнер. Фи так делать.

Не только читать, а тратить время на освоение, на внедрение в существующие автоматизированные и не очень процессы.


Я чуть выше писал уже, docker-compose описан в документации к докеру. Просто вы к молотку инструкцию еще не до конца прочли, а уже в прод его притащили. Ай-ай-ай так делать.

Проводить аудит безопасности на каждый апдейт.


Я вот вам, например, и предлагаю, проводить аудит безопасности на само приложение, а не на приложение + СУБД.

Следить за лицензионной чистотой.


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

Системы с требованиями к масштабированию, отказоусточивости и т. п. никто не отменял.


Контейнер приложения с упакованным внутрь постгресом ортогонален и масштабированию, и отказоустойчивости. Точнее не так, противоречит обоим требованиям.
В dpkg-deb --build и компанию


Он вам зачем понадобился, собственно? /usr/local, в конце концов, отменили, что ли?

Например, собрали образ локально, потестили слегонца и запушили его как-то на сервер QA для текущей ветки, а после апрува — на прод.


Собственно, CI/CD ломанулось в рост сильно раньше докера. Я бы связал «становление технологии» скорее с git'ом. Докер появился после.

Теперь о нюансах конкретно в этих кейсах. У вас приложение + СУБД. У разработчика есть локальная копия базы, протухшая как хз что, 100500 раз поломанная и все вот это. Небольшая такая база — на пару тысяч записей, чтобы сильно машинку не грузить. И вот запилил он новую уберкрутую выборку, все норм… на 2000 записей в базе. И думает наш разраб «проверить бы, как оно живет на 3-гигабайтной базе, не нужно ли по быстрому пагинацию прикрутить, или и так норм». И вот тут вы со своим «БД в контейнере с приложением — это нормальная практика» для тупой проверки предлагаете ему либо засунуть это на QA, «чтобы посмотреть, не загнется ли все это разом» (а за это ни тестеры, ни другие разрабы спасибо не скажут), либо вытянуть себе на локалхост 3-гигабайтную базу и ворочать все это локально.

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


Упаковка СУБД — тем более. Зачем упаковываете?

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


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

Current versions of Docker include swarm mode for natively managing a cluster of Docker Engines.


Ага, только в виде docker + docker-compose + «swarm mode on». Вы инструкцию не дочитали.

По поводу «готовности docker-swarm к большому проду» у «большой четверки» свое мнение, конечно… Однако даже сами разработчики докера для управления «кластером» предлагают именно docker-compose.yml, который на «вашем кластере» — лишняя сущность.

k8s для наших задач выглядел как из пушки по воробьям.


Очень вероятно, вместо него предлагается docker-compose.yml + swarm.

Да, кстати, наши многопроцессные «бандлы» ближе к подам логически, чем к системам на docker-compose.


Как раз вряд ли. Вы, как разработчик, должны, вроде, понимать, что такое «уровень абстракции». Ну вот управление ресурсами должно происходить на более высоком уровне абстракции, чем предоставляет dockerfile. Прям в официальной доке написано: уровень контейнера => уровень сервиса => уровень стека. Вот уровень стека в терминологии докера — это аналог пода. А на уровне докерфайла такое делать не рекомендуется.

Не рассматриваем мы сценарии где инстансы СУБД шарятся между разными системами.


Ну вот зря же, СУБД уровня postgre изначально проектировались именно под эти кейсы. Как вы ни убивайтесь, постгре не станет неотъемлемо интегрируемой частью вашего приложения. Он всегда «сбоку», он так работает. И смысла бандлить внутрь контейнера его нет, такова жизнь.

Одно развёртывание системы — один инстанс СУБД (или один кластер, если считать нескколько инстанс связанных «ручной» репликацией за кластер).


В смысле, вы между инстансами «приложение + СУБД» еще и репликацию поднимаете? И «настройка связи между контейнерами» осилили? Простите за откровенность, «Слабоумие и отвага» — ровно то, что надо написать над входом в вашу организацию.

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


У вас, видимо, мощностей лишних дофига?

Там где видим — разбиваем на десятки контейнеров с десятком инстансов СУБД на одно разворачивание.


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


«Версионирование БД» — вполне отдельная тема со своими практиками. И она к докеру ортогональна, т.е. его средствами не решается никак.

А общий сервер СУБД — пробовали, плюсом было экономия ресурсов, минусом — конкуренция за ресурсы, одновременное падение всего и вся


Купите консультацию DBA, что ли. Полезнее будет, честное слово.
а) применимо в проде
б) соотвествует требованиям изоляции
в) во многих организациях десятки серверов БД даже для зависимых приложений или систем, не говоря о независимых. Ну и тот же (микро)сервисный подход часто подразумевает свою базу для каждого (микросервиса)
г) иные способы конфигурации
д) не ведёт к отказу, а показывает ненужность или дорговизну на данном этапе развития приложения/системы. Например, одно дело если у вас на поток поставлена контейнеразция приложений, а совсем другое если это разовая задача, требующая дополнительного обучения персонала даже для «всё в одном».
а) применимо в проде


Реально? Запилить контейнер, внутри которого 25% памяти отдать постгресу, а что осталось — вебморде с обвязкой вокруг гита — это применимо в проде? Давно это норма?

б) соотвествует требованиям изоляции


Требования в студию.

в) во многих организациях десятки серверов БД даже для зависимых приложений или систем, не говоря о независимых.


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

Ну и тот же (микро)сервисный подход часто подразумевает свою базу для каждого (микросервиса)


Никогда, ни при каких условиях SOA (которую вы называете микросервисным подходом) не предполагала отдельную базу для каждого ИНСТАНСА сервиса. Бред это потому что, и противоречит логике.

г) иные способы конфигурации


Прибить базу к локалхосту принято читать как «отсутствие способов конфигурации»

д) не ведёт к отказу, а показывает ненужность или дорговизну на данном этапе развития приложения/системы.


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

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


Т.е. docker run обучения персонала не требует, это все с рождения умеют, а docker-compose up — сверхсложная наука, которой по 6 лет в университете учат?
Реально? Запилить контейнер, внутри которого 25% памяти отдать постгресу, а что осталось — вебморде с обвязкой вокруг гита — это применимо в проде? Давно это норма?

От прода зависит.


Десятки серверов БД в кластере, с настроенной репликацией, фейловером и т.д.

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


Никогда, ни при каких условиях SOA (которую вы называете микросервисным подходом) не предполагала отдельную базу для каждого ИНСТАНСА сервиса. Бред это потому что, и противоречит логике.

Далеко не все считают MSA хотя бы подмножеством SOA, не то что синонимами. А кто говорит для каждого инстанса? это ваши фантазии. Одна база на все инстансы. Просто частный случай когда их всего один.


Прибить базу к локалхосту принято читать как «отсутствие способов конфигурации»

У кого принято? А если база не постгри и вообще не сетевая?


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

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


Т.е. docker run обучения персонала не требует, это все с рождения умеют, а docker-compose up — сверхсложная наука, которой по 6 лет в университете учат?

Требует. И обучение docker-compose up включает в себя обучение docker run сначала.

От прода зависит.


Вне зависимости от прода ограничение «25% памяти — постгресу» в докерфайле непереносимо. Т.е. «дистрибуцию», «масштабирование», «воспроизводимость окружения» и все вот это мы вычеркиваем, т.к. ничего воспроизводить, масштабировать и распространять вы не собираетесь. Остается только «изоляция». Т.е. вы хотите просто один раз это настроить, запустить, чтобы оно как-то работало и не подралось с соседями. Дык, для этого есть более другие, ГОРАЗДО более приспособленные под кейс инструменты. Возьмите, блин, LXD — это контейнер ОС, он ровно для этих случаев пилится. Это как виртуалка, только с изоляцией на уровне ядра, в смысле, с тем же оверхедом, что и докер. Зачем вы пытаетесь ВСЕ в докер запихать. Я, конечно, понимаю, что дай вам в руки молоток, вы все за гвозди посчитаете. Просто как доктор вам говорю: шурупы удобнее закручивать отверткой.

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


Т.е. у вас есть десятки серверов БД разных версий, некоторые с репликами, все это как-то балансируется, масштабируется и все вот это… А вы постгре в каждое приложение бандлите! Красавцы!

Далеко не все считают MSA хотя бы подмножеством SOA, не то что синонимами.


Ну вот зря они. Ничто, как водится, не ново под луной. Все с завидной регулярностью переизобретается. Микросервисы — это ровно переизобретенная SOA, только ближе к практическому применению на более узких кейсах + некоторый набор устоявшихся практик.

А кто говорит для каждого инстанса? это ваши фантазии. Одна база на все инстансы. Просто частный случай когда их всего один.


Вы говорите, что одна база для каждого инстанса же! Понимаете, забандленная в контейнер с приложением СУБД — это и есть одна база на ИНСТАНС. Или вы, в смысле, собираетесь один volume с файлами СУБД в несколько контейнеров подмонтировать, чтобы НЕСКОЛЬКО СУБД-ДВИЖКОВ с одним набором файлов работало? Кхм, вы точно ничем не больны?

У кого принято? А если база не постгри и вообще не сетевая?


Я же, вроде, достаточно четко говорил: постгри или любые СУБД того же уровня пихать в один контейнер с приложение — говно подход. Если база не сетевая — вопрос отпадает сам по себе, но это НЕ энтерпрайз-субд уровня постгри, это, как правило, sqlite. Вот она, как раз, отлично подходит для того, чтобы ее вольюмом в контейнер пихали. А постри — не подходит. Только, пожалуйста, sqlite тоже не монтируйте в 2 контейнера одновременно, она, как бэ, single-user БД.

Ну и, собственно, почему вы считаете, что база, прибитая к локалхосту — это отличный способ конфигурации. Что вы там на уровне подключения поконфигурировать можете? Вместо 127.0.0.1 в параметрах подключения localhost ввести?

Нет, в некоторых случаях показывает факт того, что собрано в условиях ограниченных ресурсов.


Конкретный кейс собран в условиях «вау, есть же докер! Давайте соберем образ, чтобы еще одну галочку поставить в графу СПОСОБЫ РАЗВОРАЧИВАНИЯ. Вот, например, наша техничка Алёна докерфайл набросала, я проверял, на моем компьютере запускается, давайте положим это на оф. сайт.» И не надо про ограниченные ресурсы. Не надо тратить и без того ограниченные ресурсы на выпуск говна.

И обучение docker-compose up включает в себя обучение docker run сначала.


А это, простите, нахрена?
Понимаете, забандленная в контейнер с приложением СУБД — это и есть одна база на ИНСТАНС.

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


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

Это лишь частный случай «одна база на все инстансы», когда «все» равно единице.


Мсье философ. Только он с логикой не дружит. При количествоИнстансов != 1 высказывание ложно, поэтому с «частным случаем» оно ничего общего не имеет.

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


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

независимого масштабирования процессов приложения и процесов базы


Вот эта часть — она в архитектуру и концепцию СУБД заложена ИЗНАЧАЛЬНО. Т.е. вы сначала поломали к хренам саму концепцию, а потом, «в случае чего», будете «героически преодолевать» собственные грабли, заботливо разложенные вами же в результате вашей «нормальной практики докеризации процессов». Гениально, зато вы всегда при работе, всегда есть за что денежку получать.

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


Вот! Мы становимся «предметнее». Ок, под инстансом мы подразумеваем конкретный экземпляр, запущенный в рамках развертывания. Предлагаю сразу остановиться на этой терминологии: развертывание — это логически определяемая штука, состоящая из инстансов приложения и их ресурсов. Теперь осталось понять, зачем вы подходом «база в бандле» уравниваете «развертывание» и «инстанс». Понимаете, разным инстансам приложения внутри одного развертывания может понадобиться доступ к общему инстансу БД. Это, как раз, называется «нормальная практика». Т.е. вы можете иметь 1 БД на развертывание, и при этом поднять несколько воркеров/веб-интерфейсов и т.д. и т.п. поверх этой БД, в порядке «балансировки нагрузки», «отказоустойчивости» и т.д. Вы же прибиваете каждый инстанс приложения к собственной БД, и даже внутри развертывания уже ничего не можете изменить.

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

Понимаете, есть «инстанс приложения» — это уровень докера, есть «экземпляр развертывания» — это уровень ОРКЕСТРАЦИИ. Представьте себе приложение, которое хочет СУБД, кеш, очередь, продвинутую систему логгирования и еще 10 компонент, которые мне прямо сейчас в голову не приходят.

Вы, конечно, все это можете запихать в один контейнер, только вместо «оркестрации развертыванием» (вокруг которой уже есть достаточно обширный устоявшийся инструментарий) вы получите «оркестрацию процессами», вокруг которой копья ломают уже не одно десятилетие, а вот именно ее (все эти иниты, systemD и прочее) из вашего базового докер-образа отпилили за ненадобностью с мотивацией «докер не для этого». И вы эту оркестрацию начинаете писать на столь нежно нелюбимых вами шелл-скриптах. Отличный подход, так держать!

И база делиться между разными развёртываниями не должна.


База должна делиться, как минимум, между разными инстансами внутри одного развертывания. База внутри контейнера делиться не будет.
В этом отношении, конечно, all-in-one (в РАЗУМНОЙ мере) существенно проще и не тянет за собой ворох этих проблем.

Вы же понимаете, что простенькая веб-морда над постгре-БД, упакованная в контейнер с базой данных не может считаться «all-in-one в разумной мере»?
Ну, например, требования доступа к СУБД через файловый сокет, а не сетевой.

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

Откуда больше? Постгри в контейнере почти анлогичен постгри на отдельном хосте с точки зрения основного приложения.


Ну вот мы и пришли к тому, что постгре на локалхосте для самого приложения абсолютно идентичен постгре в сети. Теперь все же вопрос: с какой целью вы отказываете пользователю в возможности использовать remote постгре, при этом еще и в контексте «контейнера приложения». Философия у докера достаточно простая: запускаем процесс в изолированном окружении, как только процесс загнулся — киляем окружение до кучи. Это просто и это работает. Как только вы прикручиваете контроль запуска соседних сервисов при запуске приложения и впиливаете gracefull shutdown в код самого приложения — вы обкладываетесь граблями. Как только вы прикручиваете supervisord и прочие иниты в качестве основного процесса в докер — вы обкладываетесь граблями. Если вам нужен полноценный инит с контролем зависимостей, с графом запуска и прочей фигней, не родной для контейнера приложения, возможно, вам просто нужен контейнер ОС?

Нет, можно, конечно, «пробивать» изоляцию докера, «прибивать» гвоздями один контейнер к другом, шарить между ними те же файловые сокеты через docker-compose и прочее, но зачем если все проблемы взаимодействия между контейнерами можно решить помещением всего что нужно нашей системе в один контейнер?


Потом юзер ставит ваш «чудесный сервис» с постгре унутре к себе на машинку, и все чудесно… Ага… Рядом он поднимает еще парочку, и вуаля, у него 3(три!!!) постгреса, работающие на локальной машинке. А потом он в этот зоопарк запускает еще пользователей, штук 10. И долго думает на тему: почему все встало раком. А потом до него доходит, что 3 постгри на одной машине не есть хорошо, и он поднимает себе отдельную машинку с целью унести «БД вашего гитлаба» туда… А потом он читает 150-страничный мануал по докеру на тему «как распилить один всратый докерфайл на два, чтобы ничего не поломалось». И даже распилил, а ваш божественный образ только по файловому сокету в базу ходить умеет…

Вот и пытаюсь я понять, ЗАЧЕМ вы это делаете?
> С какой такой целью вам потребовалось прибить гвоздями коннект к постгре к файловому сокету в условиях докерной изоляции?

Не в условиях докерной изоляции, а докером оборачивали уже существующую конфигурацию.

> Ну вот мы и пришли к тому, что постгре на локалхосте для самого приложения абсолютно идентичен постгре в сети.

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

> с какой целью вы отказываете пользователю в возможности использовать remote постгре

Нам так проще.

> Вот и пытаюсь я понять, ЗАЧЕМ вы это делаете?

Для упрощения жизни. Максимально приближаем различные окружения к проду. Если на проде крутится пресловутый гитлаб на одном «локалхосте» через файловый сокет, то и в докере пускай тоже так крутится. Когда админы прода решат вынести базу гитлаба на отдельный сервер, тогда и мы внесём изменения в докерфайлы и докер-композ.
Не в условиях докерной изоляции, а докером оборачивали уже существующую конфигурацию.


Т.е. «исторически сложилось» уравниваем с «нормальная практика»?

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


Или к DNS привязаться, или авторизацию по ключу настроить, или SSL включить. Довод «нам было сложно 1 раз настроить доступ к постгре, и мы решили прибить его гвоздями к локалхосту» — слабый аргумент, имхо. Экономия на спичках — это такое себе.

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


У вас прод какой-то странный. Ну либо у вас проблемы.
> Т.е. «исторически сложилось» уравниваем с «нормальная практика»?

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

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

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


Нормальная практика — это подход, в котором «быстрая контейнеризация существующих приложений» производится человеком, сколько-нибудь компетентным в вопросе. «Деплоить и доставлять» действительно, можно и обезьяне доверить, эта вещь приемлемо автоматизируется. А вот автоматизация процесса, как показывает практика, автоматизируется из рук вон плохо.

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


Докер — хреновая обертка для доставки stateful-приложений. Если хочешь доставить на локалхост — самый-самый инструмент для кейса — docker-compose.

«Не следует множить сущее без необходимости» тоже слабый довод?


Множить сущее — это вы куда-то замахнулись. В оригинале про сущности было, например. Вы просто вместо того, чтобы средствами оркестрации рулить абстрагированными сущностями а-ля контейнер, почему-то предпочитаете помножить низкоуровневые сущности внутри контейнера. При том, что для оркестрации ресурсов на уровне контейнеров существует ряд решений, которые как-то развиваются и отлаживаются. А для оркестрации костылей внутри контейнера решений нет и не предвидится, рекомендуют подход «залей это лавой».
Нормальная практика — это подход, в котором «быстрая контейнеризация существующих приложений» производится человеком, сколько-нибудь компетентным в вопросе.

Если человек быстро выполнил задачу по контейнеризации, причём быстрее и гораздо дешевле, чем сторонние профессионалы, то он достаточно компетентен.


Докер — хреновая обертка для доставки stateful-приложений.

Практика показала, что лучше чем bash-скрипты.


В оригинале про сущности было, например.

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


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

Если человек быстро выполнил задачу по контейнеризации, причём быстрее и гораздо дешевле, чем сторонние профессионалы, то он достаточно компетентен.


Вах, до классики добрались. Про «Быстро, дешево, качественно — выбери два» слыхали? Оно правда!

Вы сами выбрали «быстро» + «дешево», зачем вы пытаетесь ЭТО выдать за «качественно»?

Практика показала, что лучше чем bash-скрипты.


Она же показала, что хуже, чем виртуализация, LXC/LXD, flatpak, snap. При этом докер отлично работает для доставки ЧАСТЕЙ/МОДУЛЕЙ распределенных stateful-приложений в условиях наличия оркестрации (compose, swarm, k8s — все вот это). При этом практика крупных корпораций подсказывает нам, что и для этих задач конкретно docker сильно не оптимален, и в том же k8s, например, от самого докера только build-фаза и осталась. Возможно, тоже не надолго.

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


Латинский словарь говорит нам: ens с латыни может переводиться как «существующее, сущее, существо, вещь».
Русский словарь говорит нам:
Сущее — категория онтологии, чаще всего употребляющаяся в современной философии для обозначения как всей совокупности имеющихся наличных вещей, животных, растений, людей, так и для каждой отдельной вещи. Иногда слово «С.» употребляется как синоним «бытия», иногда (у М. Хайдеггера) как нечто противоположное бытию.
В разные исторические эпохи С. интерпретировалось различным образом.
… тут пропускаем про античность и средневековье и сразу переходим к новому, текущему пониманию, мы же на современный русский, а не на старославянский переводим…
В Новое время под С. понимается совокупность внешних причин, вещей и условий, и даже сам человек — вещь среди остальных вещей, хотя и центральная вещь. С. — то, что открывается нам в представлении, это сцена, на которой человек представляет, разыгрывает свои сценарии. Оно распадается на совокупность причинно-следственных связей; оно уже не захватывает, не угрожает, а становится «картиной мира», и отношение человека к нему теперь определяется мировоззрением.


Т.е. в современном понимании «сущее» — окружающая нас действительность, реальность.

Entia non sunt multiplicanda praeter necessitatem


Вот это нам говорит оригинал изречения. Постарайтесь заметить entia в самом начале. Это форма множественного числа слова ens.

Другими словами, вы считаете, что исходная фраза говорит о том, что без необходимости не нужно плодить «окружающие дествительности»? Или «параллельные реальности»? Или, может, вы, все таки, в латинском словаре после «ens — сущность» запятую не заметили и продолжение списка возможных от контекста переводов? Или таки не улавливаете разницу между i10n и l18n и искренне верите, что перевод легендарным «Промптом» — вершина эволюции переводов? Все таки «сущее», и вам лучше знать, и там вообще ничего общего с методологическим редукционизмом?

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


Печаль-бида. Только что про SOA и MSA рассказывали, а теперь связи настроить сложно?

Та самая оркестрация.


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

А если в один, то никакой особой оркестрации контейнеров не нужно


И докер тоже тут не нужен, вам LXC/LXD нужен.

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


Вы бредите. Когда ж вы с 2008-го года «наработанные десятилетиями практики» наработать успели-то???
Докер — хреновая обертка для доставки stateful-приложений. Если хочешь доставить на локалхост — самый-самый инструмент для кейса — docker-compose.

docker-compose — хреновая обертка для docker.
Тогда уж лучше обмазаться systemd-юнитами и раскатать все через ansible/salt/puppet
docker-compose — хреновая обертка для docker.


Даже не спорю.

Тогда уж лучше обмазаться systemd-юнитами и раскатать все через ansible/salt/puppet


А вот тут от «конечной цели» зависит. Если предположить, что вы хотите потестить какой-то сервис в пределах локалхоста с целью определить «стОит ли оно того» и потом «малой кровью» мигрировать это на нормальный кластер k8s, например, то, пожалуй, самый норм вариант. Ansible/salt/puppet/systemD вас не «изолируют», да и «подчищать» придется. К тому же рожать вот эту всю обвязку на «попробовать» — так себе занятие.

В общем «на пощупать» — compose нормальный и самый бескровный/с минимальным порогом вхождения вариант. Всяко лучше, чем в докер-образ СУБД зашить вместе с приложухой. В «боевом» развертывании, конечно, свят-свят)
Т.е. «исторически сложилось» уравниваем с «нормальная практика»?

Почему Вы отказываете в этом? Есть проблема, было предложено решение. Если решение решает задачу (быстро, дешево, стабильно) — почему следует его выкидывать?
Если решение решает задачу (быстро, дешево, стабильно) — почему следует его выкидывать?


Конкретно по кейсу с «быстро» и «дешево» — соглашусь, пожалуй. Насчет «стабильно» — недоказуемо в принципе, и «чревато». И на «нормальную практику докеризации» вот прям вот никак не тянет. Я не против, внутри своих локалхостов/организаций/кластеров — пофиг на масштаб трагедии, не существенно в контексте нашего разговора, можно творить все, что угодно. Только на людях называть это «хорошей практикой» не надо.
UFO just landed and posted this here
Кстати, с впн я действительно наелся, т.к. запустить ВПН демон в одном контейнер, а потом прилинковать сервис к нему снаружи — это реальная боль. Как одно из ограничений разделение сетевого стека между несколькими контейнерами: впн отвалился, мы его перезапустили, а контейнер с сервисом не видит впна. Приходится перезапускать и его тоже.
Проще впн и сервис запускать в одном. Подтверждаю.
А с чего это вдруг приложение будет запускать postgres? Или что вы имеете виду под приложением?

А вообще сама идеология докера: один процесс — один контейнер. Т.е. если вы хотите запустить банальный LAMP, то надо запускать 3 контейнера: apache, php (рассматриваем вариант php-fpm), mysql.

Ну а так конечно никто не мешает запускать какой-нибудь supervisord и уже из под него, хоть 100500 процессов, но это будет идеологически не правильно.
Апач, пхп, мускуль, постгри и прочие обычно работают в режиме один мастер процесс и множество воркеров (могут быть однотипными, могут быть специализированные). Запускаешь вроде один процесс, но он порождает десятки, сотни и тысячи.

Нужно уточнить что такое докер контейнер. Это бизнес-единица, единица масштабирования сервиса, единица развертывания или что еще. Концепция «один процесс — один контейнер» слишком ограничена. И в лучшем случае просто приведет к излишнему раздроблению микросервиса на нанокомпоненты

Нужно уточнить что такое докер контейнер. Это бизнес-единица, единица масштабирования сервиса, единица развертывания или что еще.


Чем бы вы докер-контейнер не считали, идея запихать сервис в один контейнер с БД — хреновая.

Единица масштабирования? Ок.
Представим кейс: есть внешнее апи, тяжелый воркер под ним и БД, откуда воркер данные берет/пишет. И все это в одном контейнере…

… И стал контейнер, как водится, тормозить. При этом выяснилось, что воркер не вывозит. Вот тупо два штуки запустить, и ок… Ан не так это и просто! Берем и перепиливаем весь контейнер с нуля!

База колом встала? Кластер бы поднять, да соседние контейнеры не трогать? Нельзя — у вас контейнер монолитный, перепиливаем с нуля.

Ну вот зачем это все, если можно было в самом начале просто один компоуз-файл написать?

Единица развертывания? Вы реально в прод-развертывании собираетесь этим рулить голым докером? У вас один фиг «в бой» оно пойдет из-под какого-нибудь k8s с вероятностью процентов 80. Т.е. все равно оркестрация будет, декомпозируйте задачу ДО того, как она стала вашей проблемой.
БД (именно БД) -лучше выносить наружу и потреблять как DBaaS (например, managed instance). А вот кэш (локальный) — почему и не засунуть в контейнер?
Я считаю, что просто нужно быть достаточно гибким и не принимать все рекомендации на веру. У всего есть свой trade-off.

У вас один фиг «в бой» оно пойдет из-под какого-нибудь k8s с вероятностью процентов 80
Правильное решение. Кто спорит?
Собственно, триггерился я больше на идею «весь LAMP в одном контейнере, а чо нет?». Вот эта идея и прочие «эталонные реализации» с «постгресом внутри контейнера» — изначально очень плохая практика в 99% случаев, и я с ходу не могу придумать кейса, в котором такой подход хоть сколько-нибудь оправдан. Даже как «поиграться с локальным гитлабом» — достаточно «пахнущее» поделие. Натягивать СУБД на практики контейнеров приложений — это как «сова и глобус», в теории можно, но идея заведомо плохая.

А локальный кеш — почему бы и нет. С нюансом, опять же, в скорости «прогрева» кеша. В проде «прогревающийся» по 10-15 минут инстанс может вылезти боком, «на вырост» надо трейд-офф таки планировать.
В моих задачах сервис и без кэша (в смысле — в нем нет отдельного редиса, memcached или типа того) может 10-20 минут запускаться. Это не является проблемой как таковой, если нормально написаны health и readiness пробы, а также имеется документация как с этим жить.
UFO just landed and posted this here
Спасибо за уточнение насчет пода — оно действительно существенное.
Нюанс в том, что «единица развертывания — под», как раз, отрицает подход «докер-контейнер как единица развертывания».

Связность сервисов/уровня данных обеспечивается на уровне пода, нет смысла городить все это внутри докера, не для того он. На уровне инициализации контейнера та же БД должна быть ссылкой, откуда ее взять. Не надо внутрь него движок базы данных тащить, плохая это идея.
UFO just landed and posted this here
требуется, например, какая-то специфичная взаимная настройка компонент и делить их на образы нецелесообразно.


О какой «взаимной настройке компонент» мы говорим в случае Postgre? Постгре «калибруется» под железку, на которой он крутится, под размеры базы и прочие специфические вещи. Т.е. он калибруется конкретно под задачи и окружение. Приложение, которое с ним работает, для работы с постгре во «взаимной настройке компонент» не нуждается. От слова «никак». Оно просто должно получать на вход одну строчку с описанием «куда к базе коннектиться». При этом, при росте базы, миграциях и изменениях структуры базы постгре можно беспроблемно перенести на другую машинку, дать ему больше памяти или io… Хотя, нет, в случае, если он у вас в том же контейнере лежит — нельзя.

При этом представим ситуацию: вы мне дали образ с упакованным внутри приложением + постгре. Мне понравилось, я нашел еще 10 приложений с таким же «профессиональным подходом». Вуаля, у меня на локалхосте крутится 11 (одиннадцать, Карл!!!) инстансов постгре. При этом каждый из них стремится отожрать всю память, которая ему доступна, в целях кеширования (мы же не думаем, что человек, не способный настроить ручками коннект к постгре, способен грамотно лимитами разделить 11 инстансов этого самого постгре в пределах одного инстанса).

Нету такого кейса за пределами вашего личного локалхоста, где упаковка постгре в один контейнер с приложением — хорошая идея. И если «у меня на локалхосте все норм», это не значит, что стоит пытаться выдавать это за сколько-нибудь хорошую практику.
Касательно 11 инстансов постгреса все не так просто. Вроде бы ответ очевиден, но нет. Линукс прекрасно умеет в CoW и KSM, что в теории может существенно сэкономить память. Предполагаю, что проверить гипотезу достаточно просто: сделать набор образов с одной версией исполняемого файла и посчитать факт. расход памяти. И, да, если используются разные версии, то это уже другая история, но я запросто могу представить ситуацию, что на одной машине нужно несколько версий postgres (или любого другого сервиса).
Линукс прекрасно умеет в CoW и KSM, что в теории может существенно сэкономить память.


Как вы будете «экономить» память 11 раздельных кешей постгреса — большой вопрос.

А еще, допустим, большой вопрос, нафига я буду поднимать 11 локальных инстансов постгреса, при условии, что у меня, например, есть отдельный сервер под эти задачи.
Как вы будете «экономить» память 11 раздельных кешей постгреса — большой вопрос.

Я не говорю, что я буду «экономить». Я говорю, что утверждение, что 11х постгресов ест 11х памяти совершенно может не соответствовать действительно. К тому же, я с трудом представляю как эта конструкция уместится в одну физическую машину (или она очень большая?). Т.к. запускать постгрес в условном контейнере с веб-сайтом так себе идея — выглядит как из пушки по воробьям.
А еще, допустим, большой вопрос, нафига я буду поднимать 11 локальных инстансов постгреса, при условии, что у меня, например, есть отдельный сервер под эти задачи.

ну, так запускайте. И потребляйте как DBaaS или standalone DB с прописыванием всех конф. параметров в потребляющих эту «услугу» сервисах. Но вообще по уму это будет отдельным требованием к самим (микро)сервисам.
Я говорю, что утверждение, что 11х постгресов ест 11х памяти совершенно может не соответствовать действительно.


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

К тому же, я с трудом представляю как эта конструкция уместится в одну физическую машину (или она очень большая?).


Ну, как бы в 96Гб + 16 ядер — чо бы и нет… Другое дело, что оно будет работать как гогно и заведомо хуже, чем 1 постгрес со всем этим великолепием в его полном распоряжении на 11 баз.

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


О! Вот именно эту точку зрения я и отстаиваю, что говно вариант. А мне тут «нормальная практика, нормальная практика».

И потребляйте как DBaaS или standalone DB с прописыванием всех конф. параметров в потребляющих эту «услугу» сервисах.


Дык, я так и хочу. И утверждаю, что разработчик, который мне отдал докер-образ с зашитым внутрь вместе с приложением постгресом — м.дак и нихрена не понимает в том, как готовят контейнеры. А меня тут в 3 жала пытаются в обратном убедить, аргументируя это тем, что «вон гитлаб же упаковали, значит и нам всем так делать надо».
Они же в «изолированном окружении» выполняются, как минимум слабо верится, что в изолированном контексте ядро может «расшарить» память между процессами.

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

Неправда ваша. И приложение, и база должны, как минимум, использовать один способ подключения. А не так, что постгри сеть слушает, а приложение по файловому сокету стучится. Если приложение по сети не умеет, то постгри нужно настраивать под приложение. Да и и даже если всё «по науке», то обычно базу подстраивают под основного клиента, а не наоборот.

> При этом представим ситуацию: вы мне дали образ с упакованным внутри приложением + постгре. Мне понравилось, я нашел еще 10 приложений с таким же «профессиональным подходом». Вуаля, у меня на локалхосте крутится 11 (одиннадцать, Карл!!!) инстансов постгре.

Чем отличается от ситуации, когда я вам дам docker-compose в котором есть и postgre? Причём может быть не просто тупо в приложени строка с подключением передаётся, а постгри в докер-композе описан как сервис, причём не просто ссылка на офобраз и установка env параметров, а или свой образ, или с монтированием конфигов, или и то, и другое и что-нибудь третье типа генерации конфигов постгреса на лету. Тот же список разрешенных для коннекта айпишников.
Неправда ваша. И приложение, и база должны, как минимум, использовать один способ подключения.


Ага, один способ подключения, который, согласно общепринятой практике, передается в контейнер с приложением в виде переменной окружения… Не я придумал, все так делают.

Если приложение по сети не умеет, то постгри нужно настраивать под приложение.


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

Чем отличается от ситуации, когда я вам дам docker-compose в котором есть и postgre?


Тем, например, что я смогу передать другое подключение к постгре воркер-контейнеру. А то, которое «в бандле», не юзать.

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


По пунктам:
1. Если воркер-контейнер не принимает в качестве ключа конфигурации подключение к произвольному постгре-серверу, автор контейнера — рукожоп, например.
2. Постгри в композе описан как сервис? А есть другие варианты? В котором он описан не как сервис? Какой ужас, вас его еще и использовать заставляют?
3. Свой образ с монтированием конфигов? Отличная шпаргалка, каких конфигов авторы желают постгресу для нормальной работы? Не? Можно сконфигурять свой адекватно запросам?
4. Генерация конфигов постгреса на лету? Жуть какая! Не пользуйтесь ЭТИМ.
5. Список разрешенных для коннекта айпишников зашитый внутрь образа? Жуть, веский повод сменить образ, например.
1) приложение принимает в текстовом конфиге, конфиг монтируется в контейнер.
2) описан, но есть разные варинаты описания, например не из официального образа, а из своего с официальным мало общего имеющего.
3) локально что хотите делайте, главное чтоб в гит репу не попадало
4) а как ещё сделаете, чтобы записи в pg_hba.conf обновлялись при поднятии контейнера с приложением? Не, я знаю как: постгри в один контейне с приложением и с 127.0.0.1 доступ :)
5) в том-то и дело, что зашить можно только один по сути, 127.0.0.1 ну или вариации.
1) приложение принимает в текстовом конфиге, конфиг монтируется в контейнер.


Оно в текстовом конфиге только локальный файл-сокет принимает?

2) описан, но есть разные варинаты описания, например не из официального образа, а из своего с официальным мало общего имеющего.


И в чем суть проблемы? Постгре какой-то другой модели?

3) локально что хотите делайте, главное чтоб в гит репу не попадало


Вы неверно прочли, это вы представили docker-compose с образом, указанным разработчиками и прилагаемыми конфигами проблемой. Я как раз не вижу в этом проблемы. Вы либо берете, что вам сказали, либо смотрите в эти конфиги и поднимаете свой постгре с требуемыми настройками. В чем проблема?

4) а как ещё сделаете, чтобы записи в pg_hba.conf обновлялись при поднятии контейнера с приложением? Не, я знаю как: постгри в один контейне с приложением и с 127.0.0.1 доступ :)


Еще можно DNS воспользоваться (не надо про задержки, резолвер локальный), еще доступ по ключу, по паролю. В конце концов, если вы в изолированной подсети, поставьте пароли плейнтекстовые. Будет не хуже локального «127.0.0.1-можно-все».

5) в том-то и дело, что зашить можно только один по сути, 127.0.0.1 ну или вариации.


Зашить можно много чего, например, вплоть до «из локальной подсети можно» — прочтите доку по постгре, не айпишником единым, знаете ли.
Насчет генерации конфигов на лету — не вижу проблемы, т.к. это общепринятая практика. Как минимум — это единственный способ сделать nginx динамическим (nginx-proxy + le для докер-контейнеров). И для postgresql, к сожалению, тоже приходится баловаться этим, т.к. штатный образ обладает определенными изъянами (например, в него нельзя положить postgresql.conf в штатное место, т.к. иначе база не инитится — можете посмотреть issues в трекере как народ изворачивается).
Видел я все это. И отлично понимаю, что postgresql — это штука, которая «в лоб» без набора костылей и подпорок не докеризуется в принципе. При этом вы группой товарищей дружно в голос мне утверждаете, что от того факта, что вы эту кучу костылей положите в один докерфайл с вашим приложением, ситуация станет чем-то лучше. Что это нормальная практика. И в качестве подтверждения размахиваете образом omnibus/gitlab со словами «серьезные дядьки так делают, и нам советуют».

А «серьезные дядьки» в докерфайле прямо пишут вот такое: echo "# Prevent Postgres from trying to allocate 25% of total memory". Там еще много замечательных вещей в докерфайле, я давал на него ссылку. И все утверждают, что все норм, так можно делать и «у меня все работает, не вижу проблемы».

Понимаете, postgresql сам по себе докеризуется через огромную хитрозаверченную жопу. При этом есть возможность не делать вид, что «проблема решена» путем обрезания доступной постгресу памяти в размере 25% памяти, доступной контейнеру и прибиванием его к локалхосту, а хотя бы попробовать прикрутиться к чему-то сколько-нибудь стандартному или, уж не до хорошего, поддерживаемому.

Ан нет, все дружно утверждают, что сложить костыли постгреса в один файл с костылями самого приложения, попутно отобрав у человека возможность сделать по-человечьи — это «нормальная практика», и «отдать постгресу 25% памяти» — это нормально для боевого прод-окружения.
Ан нет, все дружно утверждают, что сложить костыли постгреса в один файл с костылями самого приложения, попутно отобрав у человека возможность сделать по-человечьи — это «нормальная практика», и «отдать постгресу 25% памяти» — это нормально для боевого прод-окружения.

Про 25% небольшая ремарочка. Нас это вообще может в принципе не волновать, т.к. хорошей практикой считается задавать максимальные значения CPU/RAM при инстанцировании контейнера. И в теории разработчик должен подумать о том, сколько ресурсов необходимо для контейнера в работе в зависимости от нагрузки на него. Поэтому если постгрессу в контейнере будет 25% памяти при условии стабильной работы контейнера под заявленной нагрузкой, то это не является проблемой от слова совсем. Если повернуть немного в другую сторону — никто же не тюнит те же (u)limits внутри контейнера (как правило)? Зачем заниматься преждевременной микрооптимизацией?
Вот смотри, мне предоставили такой «гениально затюненный продукт», который у разработчика «прямо отлично работает на локалхосте». Что внутри, яхз, предположим. И я, как умная Маша, иду на честно купленную впс-ку с 256Мб на борту и запускаю там этот гениальный контейнер. Спасибо, товарищи разработчики, за наше счастливое детство, короче.

А насчет «заявленной нагрузки» и «минимальных требований» — нифига у них нету… «Нормальный универсальный контейнер же, чо нет?»
И я, как умная Маша, иду на честно купленную впс-ку с 256Мб

э-э-э… Полегче. Какая такая VPSка с 256МБ ОЗУ? Для меня лично очевидно, что gitlab со всеми зависимости, условно, меньше, чем на 2ГБ ОЗУ как-то стремно запускать. Независимо от того, что там разрабы написали.
Но то, что документация должна быть — это непреложный факт.
«Нормальный универсальный контейнер же, чо нет?»

ЩИТО? У нас была мысль собрать кубик на говно-серверах (из серии VPS 256МБ ОЗУ). Знаете какая проблема? Да минимальное джава-приложение, которое разрабатывают наши разрабы, в такой инстанс тупо не влезет.
э-э-э… Полегче. Какая такая VPSка с 256МБ ОЗУ? Для меня лично очевидно, что gitlab со всеми зависимости, условно, меньше, чем на 2ГБ ОЗУ как-то стремно запускать. Независимо от того, что там разрабы написали.


Вот тут-то вы и зафейлитесь, если пристально докерфайл не изучите. 2Гб, минус затраты на изоляцию и прочее, да пофиг, даже их не учитываем, просто посчитаем «в лоб». Вы ожидаете, что на 2Гб при 10-15 разрабах оно будет шевелиться. А у него на постгре лимит в 25%, т.е. постгре ограничен 0,5Гб в нашем случае. При 10-15 активных разрабах конфа встанет раком на второй-третий месяц работы.

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

ЩИТО? У нас была мысль собрать кубик на говно-серверах (из серии VPS 256МБ ОЗУ). Знаете какая проблема? Да минимальное джава-приложение, которое разрабатывают наши разрабы, в такой инстанс тупо не влезет.


Вот в доках на кубик, например, прямо сказано, что 256Мб ОЗУ на ноду — плохая идея). Для четвертьгектарных нод кубик — уже оверхед, только baremetal, только хардкор.

Но, собственно, я практику авторов гитлаба нормальной не считаю. А они считают, что их методы упаковки — нормальный универсальный подход. И у них есть последователи…
> Оно в текстовом конфиге только локальный файл-сокет принимает?

Что угодно принимает, но конфиг не предназначен для редактирования пользователями. Любые изменения лежащего в репе конфига локально — «потеря гарантии». Одна из основных целей докерезации — минимизация проблем типа «а у локально работает» и «всё сделал по инструкции, но не работает».

> И в чем суть проблемы? Постгре какой-то другой модели?

Процесс конфигурирования не имеет ничего общего с официальным образом и документация по конфигурированию доступна только разработчикам.

> либо смотрите в эти конфиги и поднимаете свой постгре с требуемыми настройками. В чем проблема?

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

> Зашить можно много чего, например, вплоть до «из локальной подсети можно» — прочтите доку по постгре, не айпишником единым, знаете ли.

Есть утверждённый регламент безопасности. Думаете веская причина для безопасников будет «мы, команда разработки, тут решили сделать себе жизнь проще немного и потому просим ослабить требования безопасности»?
Что угодно принимает, но конфиг не предназначен для редактирования пользователями.


Можно поинтересоваться, какими средствами докера вы добились невозможности изменения конфига пользователем при запуске?

Любые изменения лежащего в репе конфига локально — «потеря гарантии».


Зачем его менять в репе, если его можно подсунуть при старте?

Одна из основных целей докерезации — минимизация проблем типа «а у локально работает» и «всё сделал по инструкции, но не работает».


Ложная индукция. Контейнеризация помогает в минимизации проблемы УМВР, в контексте разработки, т.к. максимально унифицирует окружение разработчика и прод. А вот в «всё сделал по инструкции, но не работает» она скорее мешает. В настройки безопасности локальной постгри рядовой пользователь залезть не может, ибо прав недостаточно. В настройки постгри, запущенной этим пользователем в контейнере — запросто.

Процесс конфигурирования не имеет ничего общего с официальным образом и документация по конфигурированию доступна только разработчикам.


Жуть какая, постгре хотя бы «той модели»? Гитлаб, условно, в принципе с постгре работает же? Собственно, в чем препятствие выкинуть к хренам «особенный постгре» и положить вместо него «обычный»? А, точно, он же на локалхосте…

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


Проблема в том, что вместо решения проблем вы пытаетесь настрать на них, закопать поглубже и делать вид, что их нет. Вместо того, чтобы протестить тупо линк до постгре-сервера и в случае отстутсвия сказать «ой, у вас ваша постгря отвалилась» вы предлагаете все в кашу захренячить в один контейнер. Не надо, блин, конечных пользователей имбецилами считать. Среди потребителей вашего продукта могут оказаться вполне вменяемые сисадмины, которые еще и вам подскажут, где косяк, и как по быстрому поправить… Хотя не, у вашего продукта таких не будет. Они посмотрят на постгре внутри, и, с криками «свят-свят» зарекутся к этому прикасаться в принципе.

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


Давно «прибить авторизацию к айпишнику, который может ручками выставить на свой бучек любая п… да, которая приперлась с ним в контору и воткнувшаяся в локалку» надежнее, чем «авторизация по доменному резолверу» или «авторизация по ssl-ключам»?

я новичок в контейнерах, поясните момент: "Не надо хранить данные внутри контейнера." — при этом советуют создать отдельный контейнер для СУБД, разве это не означает что данные в СУБД будут хранится в контейнере, который вроде как эфемерный

У контейнера с СУБД данные должны храниться не в контейнере, а на volume, который не эфемерен.

UFO just landed and posted this here
Но это нарушает правило "может быть запущено сколько угодно контейнеров выбранного типа".

Нет, не нарушает. У каждого из этих контейнеров будет свой volume. Можно сделать и общий, но см. "проверяйте, что приложения корректно пишут данные в общее хранилище".


А где хранятся миграции? Контейнер миграций, контейнер СУБД?

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

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

Контейнер миграций — ок, тем более, если потом в кубернетес поедешь. Там очень хорошо с концепцией сайдкартов и инит контейнеров

Честно говоря, сами БД в концепцию «12-факторных» приложений ложатся от слова «никак». Масштабирования БД по кластеру — это такая штука, которая средствами оркестрации контейнеров никак не решается, живите теперь с этим)
UFO just landed and posted this here
Кхм, БД разные бывают. Предлагаю не считать таки Postgre, MsSql, OracleDB и прочие махровые энтерпрайзные РСУБД устаревшим мусором, ок?

Просто вот с ними все эти штуки вроде «простое увеличение количества реплик в statefulset приведет к автоматическому масштабированию» не работают. Тем более, что выше была идея именно потгре/мускуль в контейнер засунуть. Ну так вот — это плохая идея, и вот эти вещи так не масштабируются.
Меня больше пугает не scale up, а scale down, что в штатном режиме, что аварийный
UFO just landed and posted this here
Тут есть два момента.

1) Запуск БД в Docker вообще нерекомендуемая практика, именно потому что, она предполагает наличие персистентности данных между запусками контейнера. Это противоречит идеологии Docker. Да, можно поиграть с volume, но это костыль.
2) Не докером единым. Кроме докера существуют и другие виды контейнеризации, например LXC. В LXC вполне допустимо хранить данные в контейнере.

В любом случае, использовать контейнеры только потому, что это стильно, модно, молодежно и так делают все — это глупо. Вы должны понимать, какую именно задачу вы хотите решить, и исходя из этого выбирать технологии. Если вам нужны обычные виртуалки, но вам жалко оверхеда из-за виртуализации, можно посмотреть на LXC. Docker отлично подходит в ситуации, когда вам нужно поднять N одинаковых инстансов, и N меняется в зависимости от ситуации. Увеличилась нагрузка — вы запустили еще пару инстансов, нагрузка упала — остановили лишние, оставшиеся инстансы справятся.
1) volume ничуть не костыль, а механизм для хранения состояния контейнеров.
2) LXC выглядит как набор среднеуровневых инструментов для создания высокоуровневых инструментов таких как докер.

а можно источник, откуда "запускать БД в Docker это нерекомендуемая практика"? или это вы так не рекомендуете делать?


для какого-нибудь apache вытаскивать webroot в volume тоже не рекомендуете? или вебсерверы тоже не стоит в контейнеры помещать?

а можно источник, откуда «запускать БД в Docker это нерекомендуемая практика»? или это вы так не рекомендуете делать?


Запуск БД в Docker — это, в первую очередь, достаточно бессмысленная практика.
Дело в том, что «контейнер приложения» — это такая штука, которая «сдохла, да и пофиг, рядом другую запущу» или «надо масштабироваться? Не проблема, запустим еще 158 инстансов». И вся эта возня с горизонтальным масштабированием, read-only слоями, отказом от бэкапов инфраструктуры и т.д. — она на базах данных не работает. Если вы поверх одного и того же persistent volume'а запустите две одинаковых СУБД, они просто превратят ваше хранилище в кашу, не больше и не меньше. БД просто масштабируются иначе, докер для них смысловой нагрузки не несет, только чуть-чуть лишнего оверхеда приносит.

А для отладочных целей, «чтобы не морочиться с доступом из compose» и тому подобное — да пожалуйста, не проблема.

для какого-нибудь apache вытаскивать webroot в volume тоже не рекомендуете? или вебсерверы тоже не стоит в контейнеры помещать?


Ну, сопсна, всякие «апачи» норм масштабируются, их можно. webroot — это, по факту, набор конфигов, которые апач читает на старте. Апач не генерит миллионы конкуррентных записей в вебрут, для него этот самый webroot — ридонли. Короче, не передергивайте, в случае с апачем все норм.
Апач с пхп может легко писать в webroot (говорю про php, т.к. голый апач особо и не нужен). Но это больше вопрос к корректности архитектуры самого web-приложения.
Ну, собственно, php, пишущий в webroot — это «с душком» называется, если мы в контексте «горизонтального масштабирования без боли».

Собственно, если php «какает» в webroot, то «поднять N контейнеров с этим php и смонтировать в них вольюмом один webroot на всех» — заведомо хреновая идея, например.
Ну для пхп это штатный режим работы: много воркеров (неважно mod_php или php-fpm) шарят между собой один «webroot». Особой разницы нет, воркеры это одного мастера или разных (при плюс-минус совпадающих версиях пхп, есть нюансы при сильно разных).
Собственно, я несколько далек от php и принятых в нем практик, конечно, и представления о том, что такое webroot и для чего его можно использовать, конечно, у нас могут различаться. Если под webroot'ом понимать папку с конфигами сервера, конфигурациями эндпоинтов, шаблонами для рендера, скриптами и все вот это — совершенно не вижу проблемы в совместном использовании… В readonly режиме.

Т.е. вы наконфигуряли то, что вам надо, разложили скрипты в желаемом порядке настроили, а потом все это «окружение» скормили N контейнерам (нет, N мало, пусть лучше будет K), чтобы они оттуда заинитились и начали работать — нормальный подход.

Если же вы на N контейнеров (в этом случае N уже много, лучше ограничиться M) отдали volume на запись… Кхм, даже при M=2 это УЖЕ плохая идея. Предложить нескольким процессам одновременно писать в один файл — это идея хреновая, вне зависимости от контейнеризации. В рамках одного процесса писать в файл параллельно из двух потоков — уже говнокод, простите уж за откровенность. Не надо так делать, пожалуйста. Шарить persistent volume между несколькими контейнерами безопасно только в read-only режиме.
Мне кажется, что вообще шарить код webroot между контейнерами плохая идея. Сессии пускай шарят через какой-нибудь редис. А webroot должен версионироваться и жестко инжектироваться в докер-образ (и он тоже версионируется). Надо выкатить новую версию — мы не volume обновляем, а делаем роллинг апдейт для всех контейнеров.
Спорно, конечно, но так тоже можно. Это уже от применения зависит.

Если вы пилите какой-то веб-проект и конкретно под него собираете контейнер — вполне норм подход.

Если вы хостите сторонние приложения, вам логичнее собрать преднастроенный контейнер-окружение и маппить в него пользовательские «папки», чем ребилдить образ на каждый чих от пользователя.
Какая-нибудь папка uploads с пользовательскими файлами уже пару десятков лет в пхп штатно шарится на запись между процессами. Наработаны практики, частично общесистемные (файловый ио в пхп по сути лишь легковесная обёртка над стдс), частично специфичные для пхп, позволяющие если не избегать конфликтов и взаимных локов, то минимизировать их вероятность. Как правило речь не идёт о записи в один файл (если забыть, что каталог — это тоже файл), но о записи в каталог. Но в файл тоже не исключено.

Мне кажется что есть еще один момент, который добавляет смысла в идею контейнеризации СУБД: обновление версии СУБД. Лично мне очень приятно иметь всегда чистый хост и не переживать что в результате обновления версии СУБД, а потом отката обратно (всякое бывает, тестирование не всемогуще) я не смогу вернуть систему к ее предыдущему состоянию быстро.

Осталось понять, откуда у вас уверенность в том, что контейнеризация в контексте сохранности БД вам что-то дает…
Контейнеризация — это всего лишь способ изоляции и доставки приложений. С этой точки зрения — на отдельно стоящем хосте даже БД с volume лучше запускать в контейнере.
Другой вопрос, что именно docker как реализация контейнернего движка имеет свои особенности, которые нужно учитывать.

Просто если развивать концепцию до абсурда, то каждый настоящий мужчина должен ставить постгрес (например) не из бинарного пакета (deb/rpm), а из исходников (make && make install — да, давайте замочим систему «мусором»).
Конкретно докер вообще никак не маппится на нужды поддержания консистентности БД. Вся концепция контейнеров приложений строится вокруг «мухи отдельно, котлеты отдельно».

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

Вот с вещами вроде постгреса подход не работает.
Нельзя вот просто так взять persistent volume, на котором работал 9-й постгре и примонтировать его к контейнеру 10-го. А если вы попрыгали с бубном и примонтировали таки, вы уже не сможете по-быстрому откатиться на 9-ю версию.
Собственно структура хранения данных в РСУБД, как правило, очень сильно привязана к версии движка, поэтому вот эти вещи типа «быстрых переключений между версиями безо всяких проблем» — это из разряда сказок на ночь.

Бэкап уровня данных — хорошо. При этом забэкапить контейнер ОС (предположим LXD) с развернутым постгресом и данными до кучи — гораздо более простая в реализации и более быстрая с точки зрения «восстановления» или «отката» идея. Тем более, что базы данных вроде постгре имеет смысл использовать на датасетах такого размера, когда «накладные расходы 50МБ на бэкап самого постгреса» — это совершенно малозначимая вещь.

Просто если развивать концепцию до абсурда, то каждый настоящий мужчина должен ставить постгрес (например) не из бинарного пакета (deb/rpm), а из исходников (make && make install — да, давайте замочим систему «мусором»).


Как бы ни смешно это звучало, именно необходимость сборки из исходников — самый вероятный сценарий обоснованного использования постгреса в докере. Т.е. контейнер, который сам собирает постгрес из его исходников на гитхабе одной командой — норм идея. С одним нюансом — в проде такой подход так себе идея.
Нельзя вот просто так взять persistent volume, на котором работал 9-й постгре и примонтировать его к контейнеру 10-го.
На самом деле, это так и работает. Берешь volume от 9-го, подключаешь к 10-му. Он делает какую-то магию и обновляет БД.

А если вы попрыгали с бубном и примонтировали таки, вы уже не сможете по-быстрому откатиться на 9-ю версию.
Да, правда при вышеописанном процессе запуск volume с обновленными данными со старым 9-м постгрессом зафейлится, т.к. в БД уже будет пометка, что она переконвертирована в 10-ю версию.

Это проверено на моем личном опыте.

Бэкап уровня данных — хорошо. При этом забэкапить контейнер ОС (предположим LXD) с развернутым постгресом и данными до кучи — гораздо более простая в реализации и более быстрая с точки зрения «восстановления» или «отката» идея.
бекапить постгре в контейнере тоже просто. Версия ПО и все ее зависимости — в образе, который лежит в локальном реджистри. Данные — снаружи. И их можно либо бекапить с простоем БД пофайлово, либо утилитами для работы с БД, которые умеют нагорячую. На рабочей же типовой системе — нужно бекапить И конфиги, И базу, и вероятно исполняемые модули (если какая-то хитрая схема экстеншенов). Окей, можно и только базу, но все равно все остальное нужно учитывать. Т.е. докеризация позволяет переложить сложность работы информационной системы с одного уровня на другой (в общем об этом все новомодные технологии вроде k8s)

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

В общем, все равно мы приходим к идее, что использование контейнеров весьма многогранно и не ограничивается концепцией развертывания приложений в продуктовой среде по принципу «один контейнер — один процесс».
На самом деле, это так и работает. Берешь volume от 9-го, подключаешь к 10-му. Он делает какую-то магию и обновляет БД.


Ну вот этот подход «там произошла какая-то магия, и оно теперь работает» — это малоприемлемо на боевых окружениях со сколько-нибудь ценными данными. Отмазка уровня «какая-то магия как-то там не сработала, и теперь у нас почему-то ничего никак не работает» — это плохая отмазка.
Миграция на новую версию БД — это само по себе отдельная песня, и докером она решается примерно никак. В проде — мигрируем руками, в дев-окружении… Ну, в локальных девелоперских окружениях, почему бы и нет. Но там вам, если быть откровенным, ни консистентность данных, ни надежность хранения, ни миграции какие-то не нужны. В дев-окружении необходимо иметь возможность «в случае чего в разумное время заполучить что-то работающее с какими-то правдоподобными данными». Вы же не собираетесь всерьез бэкапить девелоперскую базу?

Да, правда при вышеописанном процессе запуск volume с обновленными данными со старым 9-м постгрессом зафейлится, т.к. в БД уже будет пометка, что она переконвертирована в 10-ю версию.

Это проверено на моем личном опыте.


Вот и я о том же, происходит миграция/конвертация данных. Поэтому уровень хранения данных для СУБД, собственно, от рантайма неотделим. Так что и снапшотить проще и лучше целиком состояние системы, причем, как показывает практика, иногда с точностью до версии ядра или номера версии «третьей сверху системной библиотеки, которая, вроде, и отношения к БД не имеет»

бекапить постгре в контейнере тоже просто. Версия ПО и все ее зависимости — в образе, который лежит в локальном реджистри. Данные — снаружи. И их можно либо бекапить с простоем БД пофайлово, либо утилитами для работы с БД, которые умеют нагорячую. На рабочей же типовой системе — нужно бекапить И конфиги, И базу, и вероятно исполняемые модули (если какая-то хитрая схема экстеншенов). Окей, можно и только базу, но все равно все остальное нужно учитывать. Т.е. докеризация позволяет переложить сложность работы информационной системы с одного уровня на другой (в общем об этом все новомодные технологии вроде k8s)


Бэкапить БД на уровне логической целостности — просто сделать sqldump. Контейнер на этом уровне не дает вам ничего. Бэкапить БД на уровне физической целостности — отдельный бэкап файлов на диске, с которыми работает СУБД вам опять же ничего не даст. Оно просто не в вакууме живет, и окружение, на котором это все работает, достаточно много значит. Есть же контейнеры ОС, забэкапьте целиком. Собственно, из сценариев быстрого отката в случае БД смысл имеет только бэкап системы. В конце концов, есть же LXD и некоторые другие «контейнеры ОС», дались вам эти «контейнеры приложений».

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

К слову, тот же k8s — он вообще не эти проблемы решает. Он про оркестрацию, ничего там про организацию бэкапов/миграций БД нету, я проверял.

Ну и про «рентабельность» всего этого мероприятия (я про контейнеризацию БД). Обычно «докеризованные» сборки СУБД предполагают сценарий «запустить 1 базу на сервере». А СУБД кэшировать любят, индексы строить всяческие и т.д. и т.п. Вот с рациональностью использования ресурсов будут большие вопросы в этом подходе. Запустишь 50 инстансов, в каждом по постгресу. И ограничения выставишь, чтобы «разумно использовать ресурсы». И будет у тебя 40 баз в оперативке лежать закешированные целиком, и еще 10 дейтсвительно «тяжелых» раком встанут под нагрузкой, причем «в среднем по палате» нагрузка на сервер будет околонулевой.

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

И весь этот геморрой для решения проблемы… чего, собственно? Какую проблему мы решаем? Проблему обновления версии СУБД, которая нам встречается раз в год-два? Не та это задача, которую «автоматизируют» и «ставят на поток». Или проблему сохранности данных? Ну, собственно, и для нее контейнеры приложений решения не предоставляют. Проблему масштабирования? Не масштабируются РСУБД «в лоб» горизонтально…

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

Собственно, для этого специальный stage в докер добавили не так давно. Специальный билд-контейнер, по факту.

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


Практика показывает, что использование «контейнера приложений» типа докера офигенно себя показывает именно в схеме «один контейнер-один процесс». Подход 12-факторных приложений, воспроизводимые сборки и т.д. и т.п. — все это офигенно работает в контексте докера.

При этом она же показывает, что часть задач «контейнеры приложений» решать не способны, ну просто не маппятся эти задачи на логику контейнера. Собственно, те же РСУБД и не маппятся, собственно. В каких-то задачах докеро-подобные решения дают профит, в каких-то профита нет, а в каких-то лучше докер-со-товарищи и не трогать. И это факт.

А вот то, что «не докером единым» — это факт. Есть, собственно, тот же LXD, который «контейнер ОС». Но он решает уже другие задачи, правда из профитов «в лоб» дает разве что экономию ресурсов, т.е. «не взлетит».

Ну и, по поводу «контейнер все-в-себе-и-даже-БД»… говно подход. При этом задача уже тысячу лет как решена, есть вполне себе вменяемая оркестрация — docker-compose для мелочей на локалхосте, k8s — для продакшена и тысяча решений где-то между этими двумя крайними точками. При этом поверх того же k8s уже пилятся свои обертки… Короче, оно все растет.
Как минимум, помещение СУБД в контейнер (пока не про all-in-one) решает задачу унификации доступа к ней из других контейнеров. Где-то в продакшене контейнер с СУБД может (или даже должен) быть прибит метками и прочим к конкретному хосту, но в рамках контейнерного кластера используются обычные механизмы доступа к контейнеру со всей магией оркестратора типа сервис дискавери, внутренних днсб хелсчекинга и т. п.

Про all-in-one — вполне годный подход для определённых задач. Например когда использование докера на проде даже не планируется, и он служит лишь для быстрого развёртывания максимально близких дев и тест окружений. Как легковесная замена вагранту. Зачем городить «пробивание» дефолтной докеровской изоляции процессов в контейнерах друг от друга, если прод заточен на отсуствие изоляции?

А СУБД кэшировать любят, индексы строить всяческие и т.д. и т.п. Вот с рациональностью использования ресурсов будут большие вопросы в этом подходе. Запустишь 50 инстансов, в каждом по постгресу. И ограничения выставишь, чтобы «разумно использовать ресурсы». И будет у тебя 40 баз в оперативке лежать закешированные целиком, и еще 10 дейтсвительно «тяжелых» раком встанут под нагрузкой, причем «в среднем по палате» нагрузка на сервер будет околонулевой.

Это вообще отдельная история взаимодействия технологий — как особенности разведения нескольких JVM на одном ПК (ага, это весело). Или упаковки JVM приложений в докер.
А давайте еще вспомним, что на виртуальных машинах есть проблема «шумных соседей» и оказывается, что «любые абстракции текут» и просто нужно уметь их все готовить и понимать граничные значения, когда система «встает раком».
Вот я и говорю: не бандлите СУБД в контейнер, будет меньше граблей. А вы дружно мне все не верите.
Да причем тут СУБД?
С тем же успехом внутри docker может быть — nginx, кэш или вообще любая дичь. Докопались до одного типа ПО и продолжаете. Так можно и договориться до того, что зачем нам десяток версий системных библиотек? Давайте будем все образы штамповать из одного (на самом с т.з. стандарта и единообразия это хорошо), но это такая головная боль, что просто жесть. Я проверял — проще взять чужой проверенный образ, чем мейнтейнить свой. Более того — в случае дата сайенс — какой-нибудь «заряженный» на numpy эльпайн не дает никакого выигрыша против убунту по размеру/скорости сборки. Докер же УЖЕ абстрагирует пользователя/разработчика/админа от деталей реализации того, что внутри контейнера. И это правильно.

Короче.
  • Протащить gitlab в докер в виде единого образа в прод — можно. На маленькую компанию (если есть противопоказания против «облачного» гитлаба). Для серьезного продакшена такое решение никто не рекомендует (там нужен ha postgres, балансировщики, ha хранилище и пр.)
  • Пример, когда «база» инкапсулирована Вам привели (про тесты)
  • Уверен, что можно накидать еще 100500 вариантов, когда изначальный тезис про моно-образ не верен (хотя бы потому что приложение может состоять из множества разнородных процессов), но мне уже попросту лень

Да причем тут СУБД?


При том, что я изначально спорил только с тем тезисом, что бандлить СУБД внутрь контейнера с воркером — хреновая идея. Тем более позиционировать ЭТО как конечный продукт (для конечного пользователя) и называть нормальной практикой. Оно будет работать в пределах локалхоста, и то до поры до времени.

Протащить gitlab в докер в виде единого образа в прод — можно.


Зачем этот ужас, предназначенный для «зазырь, ОНО ШЕВЕЛИТСЯ» тащить в прод?

Для серьезного продакшена такое решение никто не рекомендует (там нужен ha postgres, балансировщики, ha хранилище и пр.)


Стоп, а до этого был какой-то «несерьезный продакшен»? Они разные бывают?

Пример, когда «база» инкапсулирована Вам привели (про тесты)


Тест-кейсы — случай сильно отдельный, там и бОльшие извращения бывают. При этом помним, что либо констракт базы на запуске теста, либо read-only ДБ. Зачем это в прод-то тащить, пусть и в «несерьезный»?

Уверен, что можно накидать еще 100500 вариантов, когда изначальный тезис про моно-образ не верен (хотя бы потому что приложение может состоять из множества разнородных процессов), но мне уже попросту лень


Про разнородные процессы я особо и не спорил, и то есть к чему придраться. Я конкретно про СУБД в контейнере.
> Зачем этот ужас, предназначенный для «зазырь, ОНО ШЕВЕЛИТСЯ» тащить в прод?

Чтобы запустить и забыть.

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

Хотите «чистую» инсталляцию с «только необходимыми данными» — я вас расстрою. Докер тут помогает «никак». Единственный путь: сдампить БД => поднять «голый» инстанс новой версии => развернуть данные из дампа. Автомиграции контейнера к «чистоте» вообще никак не ведут.

Откат на предыдущую версию, выкашивание изменений… Кхм, вы о чем? Сделайте снапшот системы ДО начала миграции. Не получилось — восстановились из снапшота. И быстро, и качественно.

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

А если так:
я забэкапил volume с БД
убил контейнер с mysql 5.6 (не volume с данными)
запустил контейнер с mysql 5.7 смонтировав ему этот volume


если надо откатить:
я убил контейнер mysql 5.7, volume с данными тоже убил
я создал volume с бэкапом
я запустил контейнер с mysql 5.6 подцепив ему этот volume


почему вы считаете что в данной схеме docker не помогает мне вернуться к стабильному состоянию системы? Или вы считаете что состояние будет не соответствовать исходному?

Прямо в этом сценарии:
1. Представим, что у вас контейнер mysql:5.6, вот прям с тэгом 5.6. При этом у вас НЕТ гарантии, что там лежит ровно тот же 5.6, что и был в предыдущем образе. В предыдущем, предположим, был 5.6.28, а в регистри уже обновился до 5.6.45 (цифры с потолка). Т.е. вы НЕ вернулись в предыдущее состояние.
2. В случае снапшота системы целиком вы просто запускаетесь из снапшота. В вашем сценарии вы убиваете контейнер, который у вас не завелся — это раз, затем создаете новый вольюм с бэкапом (кстати, он у вас КОПИЯ, т.е. где-то могли права доступа к файлам «поехать» или еще что-то по мелочам, что вы выясните уже гораздо позже) — это два, пересоздали и запустили новый контейнер без гарантии полной идентичности версии (в докер-образе mysql:5.6 5.6 — это ТЕГ контейнера, который, по джентльменскому соглашению с сопровождающими образ совпадает, вроде как, с версией мускуля, при этом не гарантированно совпадает).
Т.е. вы сделали 3 шага вместо одного, вы имеете МЕНЬШУЮ вероятность отката в предыдущее состояние.

Т.е. мы имеем:
1. Более длительный откат состояния (за помощь от докера не засчитывается).
2. Вы получили меньше гарантий возврата в исходное состояние (тоже помощью считать трудно).
3. Вы не получили внятной информации о происходящем и затруднили себе отладку всей этой ситуации (тоже, вроде, не помощь).

Понимаете, докер — это про rolling release. Вот там он цветет и пахнет. Крутить СУБД на rolling-release версиях — так себе удовольствие.
1. Если мы собираем образы сами, то мы это гарантируем. Если нет, то обычно в нормальных дистрибьюциях (нормальных пацанов, которые собирают образы, или у официальных поставщиков ПО) есть какие-либо четкие регламенты. Т.е. деплоить latest или любой другой общий тег — слабоумие и отвага (с)
Касательно разницы минорных версий — она есть, но не всегда она существенна. Мне кажется, что с минорными версиями Вы преувеличваете проблему.
2. Касательно прав. Обычно к этому моменту процесс уде отлажен и тогда такая проблема не возникнет. Либо в любом случае всегда хорошая идея проверять миграции на клоне продакшена, а не пытаться сразу что-то «на живую» сделать с продом. И тогда если полыхнет в тесте, то пойдешь изучать вопрос, а не мигрировать прод сразу
Дополнительно — всегда контейнер можно перезапустить НЕ ПО ТЕГУ, который действительно может уже иметь под собой другой образ, а по sha-сумме, которая гарантированно отличает образы и позволяет инстанцировать из образа «тот самый» контейнер

Касательно обновления бинарными пакетами (deb/rpm) или не дай Бог — исходниками — тоже так себе удовольствие
Сколько видел примеров, все сходятся на одном: автоматический апгрейд версии СУБД — хреновая идея. Тем более, что, если вы не разработчик этой субд (а 99,99% — НЕ), у вас эти апгрейды должны происходить раз в полгода-год-два-три по заранее определенному регламенту.

Делается, обычно, так: поднимается свежая версия СУБД, рядом с текущей, в нее копируются данные. Не дай Б-г вам делать апдейт на живом сервере. Вот это — слабоумие и отвага. Потом копия обкатывается, делаются необходимые миграции, тесты, эта копия тестируется на новой сборке софтины, а затем уже с танцами под бубенцы начинается непосредственно миграция.

В монолитном контейнере вы по дефолту смиряетесь, что контейнер обновляется целиком версия софта + версия базы. Одновременно.

И вот этот риск заради того, чтобы сэкономить день геморроя раз в пару лет? Нету смысла это автоматизировать, поэтому и не автоматизируют.

Дополнительно — всегда контейнер можно перезапустить НЕ ПО ТЕГУ, который действительно может уже иметь под собой другой образ, а по sha-сумме, которая гарантированно отличает образы и позволяет инстанцировать из образа «тот самый» контейнер


Смотрите, у вас был контейнер с 9-й версией постгри. Вы поверх того же датасета запустили контейнер новой версии с 10-й версией. Что-то пошло не так, миграции завалились или хз вообще что. Вы запускаете взад контейнер с 9-й версией… а миграции уже начаты, назад пути нет.
Смотрите, у вас был контейнер с 9-й версией постгри. Вы поверх того же датасета запустили контейнер новой версии с 10-й версией. Что-то пошло не так, миграции завалились или хз вообще что. Вы запускаете взад контейнер с 9-й версией… а миграции уже начаты, назад пути нет.

Это разве контейнерная головная боль? Стоял постгрес 9 на системе из пакета (официального), не в контейнере. Запустили обновление до 10-ки (не важно как, но тоже через пакетный менеджер). База смигрировала наполовину, что-то пошло не так. Как откатываться?

Нет бекапов или плана отката — ссзб. Контейнеры ни при чем
Смотри, контейнеры разные бывают. Есть, например, «контейнеры приложений» (они так и называются потому, что предназначены для запуска приложений в изолированном окружении) и контейнеры ОС (они так называются, потому что «прикидываются» операционной системой). При этом, что забавно, docker как контейнер приложения и тот же lxd в качестве контейнера ОС имеют совершенно одинаковый «оверхед» из-за того, что под капотом у них происходит примерно одно и то же.

Теперь мы попробуем представить постгре, запущенный в контейнере ОС. Мы перед обновлением бекапим целиком образ системы, с установленной версией постгре, с набором библиотек и т.д. Или даже тупо снапшотимся, что тоже работает. После этого при необходимости отката мы просто откатываемся на реальное предыдущее состояние системы, а не на пересобранный «такой же» образ. Это тупо быстрее, а контейнерная изоляция, тем более в случае «приложение в куче с БД» — это лишний геморрой.
Какие в нынешние времена есть преимущества у lxc перед docker? Я пока вижу только то, что lxc немного менее дружественная и требующая чуточку большего прикладывания рук технология.
Вы делаете странное предположение что я тащу контейнеры из общего репозитория, для продакшена я такого никогда не делаю и вам не советую. У меня есть мой Dockerfile, из него собранный образ, и в нем совершенно точно лежит именно та версия которая работала до начала обновления.

кстати, он у вас КОПИЯ, т.е. где-то могли права доступа к файлам «поехать»
— не понял вас, что значит «поехать»? При копировании файлов владельцем у файлов могут поменятся права?

Понимаете, докер — это про rolling release
я и не спорю что его так можно использовать, пока что не понял почему вы отказываете ему в функции фиксации состояния системы? Потому что вы используете готовые контейнеры и не можете полностью положиться на систему тегов?
Вы делаете странное предположение что я тащу контейнеры из общего репозитория, для продакшена я такого никогда не делаю и вам не советую. У меня есть мой Dockerfile, из него собранный образ, и в нем совершенно точно лежит именно та версия которая работала до начала обновления.


Как только разрабочиков становится более одного, это уже не гарантировано истинно.

— не понял вас, что значит «поехать»? При копировании файлов владельцем у файлов могут поменятся права?


У вас один пользователь, в смысле?

я и не спорю что его так можно использовать, пока что не понял почему вы отказываете ему в функции фиксации состояния системы? Потому что вы используете готовые контейнеры и не можете полностью положиться на систему тегов?


Вот ЭТО — эталонный докерфайл, который считается «правильным подходом» сторонниками этой точки зрения. Там прямо так и написано apt install, при пересборке мы имеем последнюю версию того, что лежит в репозитории. Каждый раз. И вот это считается «хорошим тоном» отдать конечному пользователю. ОНО может сдохнуть тупо при перезапуске в определенных случаях. Под какой-либо сколько-нибудь автоматизированной оркестрацией это запускать просто опасно.

Да, я считаю, что в данном случае НИКАК нельзя положиться на систему тегов, например. Будете убеждать меня в обратном?
Вот ЭТО — эталонный докерфайл, который считается «правильным подходом» сторонниками этой точки зрения. Там прямо так и написано apt install, при пересборке мы имеем последнюю версию того, что лежит в репозитории. Каждый раз. И вот это считается «хорошим тоном» отдать конечному пользователю. ОНО может сдохнуть тупо при перезапуске в определенных случаях. Под какой-либо сколько-нибудь автоматизированной оркестрацией это запускать просто опасно.

Так Вы смешиваете разные вещи. В теории — как только докер-образ собран и положен в репозиторий (registry) его нельзя менять и нужно тащить конкретную версию с конкретным тегом «вечно».

Dockerfile действительно не гарантирует бинарную сборку идентичную. Но это справедливо для любой другой системы сборки.
Вот смотрите, я показал вам докерфайл, который считается «эталонным так надо делать» среди сторонников подхода «БД с приложением — это нормально». Более адекватных примеров такого подхода я вживую не видел, видел только вот этот конкретный пример как это бывает. И вы даже, вроде, со мной согласны, что конечному пользователю в таком виде продукт отдавать нельзя.

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

Еще раз — зачем пользователю отдавать Dockerfile?
Пользователь делает docker pull gitlab/gitlab-ce:11.1.6-ce.0 (точное имя тега), если у него болит, или просто пуллит всегда последний (latest), если ему важно иметь последнюю версию ПО. Сам пользователь Dockerfile собирать не будет. Это ему и не надо ( и разработчикам, кстати, тоже). Проводя аналогию с deb/rpm-пакетами — их пересобирают не многие, но посмотреть КАК они собираются — могут все. Например, из соображений аудита.
А, забыл еще вот что.
Вы же КОПИЮ volume'а создадите. Это будут НОВЫЕ файлы, НОВЫЕ файловые дескрипторы и все вот это. Тот же постгре после отката на совершенно законных основаниях может начать ребилдить индексы, реструктурировать хранилище и все вот эти вещи, которые он так прикольно умеет делать, что может отсрочить возвращение базы в строй «на некоторое слабопредсказуемое время». Думаю, этот кейс мы тоже в плюсы «докеризации» записывать не будем?
И что? Не вижу связи. Никто и не гарантирует на уровне структуры БД, что одни и те же файлы БД будут попадать в те же, скажем, физические структуры вроде айнодов, но как-то живем и так?
Дело в том, что БД, как правило, не любит, когда ее файлы начинают без ее ведома перекладывать. На восстановление индекса, вероятнее всего, попадете.
Касательно снапшота — его тоже нужно уметь констстентно делать. Я уже наелся со снимками, сделанными средствами гипервизора (ага, желательно без клиентских утилит в гостевой ОС)…

К чему это я? А к тому, что кол-во уровней абстракции катастрофически выросло и нужно понимать связанные с этим риски (что и где может «протечь»)
Или наоборот: абстракции закроют доступ к важным деталям реализации.
Абстракции, закрывающие доступ к важным деталям реализации — это про докеризованное в куче с БД приложение?)
Мы говорим про более-менее сложное приложение с несколькими процессами, со множетсвом конфигурационных параметров, как независимых друг от друга, так и зависимых. Обёртка каждого процесса в контейнер если не закрывает, то осложняет конфигурирование взаимодействия процессов.
Прикол в том, что docker и lxd — это абстракции ровно одного уровня. Два инструмента поверх lxc, один из которых затачивается на умелку снапшотит состояние системы и мимикрирует под ОС, второй построен на подходе «зато можно быстро пересобрать».

Чем тот, который «пересобрать» лучше, чем тот, который «сохранить состояние»?

Редхат в своем репертуаре. Опять статья ни «о чем». Рассмотрены вроде бы прописные истины, но жизнь, как обычно, оказывается разнообразнее. Например, тезис про «один процесс на контейнер» очень хорошо опровергается примером гитлаб омнибус докер образом. Да, он не для продуктива в энтерпрайзе, но для продуктива маленькой команды или для дев/тест среды — идеально.
Также статья не дает готовых решений с описанием почему так, а не иначе. Например, тот же кейс с supervisord, tini/runit и зомби-процессами, как грамотно определять вольюм. А запуск приложения не под-рутом в докере — это отдельный способ выстрелить себе в ногу, в случае если к файлам в volume нужно еще как-то обращаться (из другого контейнера или с хостовой системы)

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

Хочу напомнить, что контейнеры — это не только docker. Еще есть, например, lxd. И там немного другая идеология.

"Другой идеологи" там нет, этот тот же Swarm, только от Cannonical.

Нет, там контейнеры чуть ближе к виртмашинам (и таки да, можно в cloud-init при наличии поддержки в образе). Нет слоев и прочего. Swarm (в терминах докера) там вообще нет. И, внезапно, нет докерфайлов. Можно персистентность.

Там используются одинаковые системные инстурменты для создания окружений.
И точно так же там есть поддержка и overlayfs, и blockdevices.
И как в Swarm, там можно управлять удалённо кластером нод и контейнерами.

Насколько помню, нет в lxd overlayfs (ну т.е. так как оно в докере, слоисто). Там все работает через снепшоты btrfs/zfs/lvm.
Swarm в докере — это не только «управлять удалённо кластером нод и контейнерами», но и этого нет в lxd (ну мы сейчас не про k8s же?).

И вот про это можно ли подробнее?

> Там используются одинаковые системные инстурменты для создания окружений.

Я имел некоторый опыт и с докером и с lxd, подходы там к сборке образов и деплою ну совершенно разные.
Одинаковые системные инструменты — факт. Те же cgroups, те же namespaces. А в целом продукт разный. Docker — это про «упаковать приложение», LXD — это «очень легкая виртуалка». Т.е. вы берете базовый образ, допустим, убунты, идете в консольку этой «виртуалки» по ssh или через локальный сокет, внутри ручками ставите, допустим, постгрес, снапшотите — вуаля, у вас новый образ системы postgres-on-ubuntu.

Т.е. у LXD внутрях полноценный инит и все вот это. А докер — запустить процесс, дождаться, пока сдохнет, убить окружение.
Не вижу преимуществ LXD. Предполагаю, что там, где он есть — там он и останется. В остальном — все перекатятся на docker.
идете в консольку этой «виртуалки» по ssh или через локальный сокет

зачем, если проще
docker exec -it <container> bash
?
идете в консольку этой «виртуалки» по ssh или через локальный сокет

ну, вероятно снапшоты «контейнера ОС» (данные+ПО) могут быть удобнее, чем фиксация изменений в ПО через Dockerfile и его сборку и резервная копия данных docker volume. Но это скорее вкусовщина, чем необходимость использовать что-то определенное.
В остальном — все перекатятся на docker.


Учитывая, с каким энтузиазмом, песнями и плясками Google, Microsoft и RedHat его хоронят, не успеют.

Дело в том, что докер очень хорош для кейсов, когда надо время от времени «пересобрать». CI/CD — там ему самое место. При этом СУБД — не такая штука, которую можно просто так взять и «пересобрать» поверх имеющегося датасета, поэтому оно в докер ложится очень неохотно, с бубном, песнями и плясками вокруг костра.

Фактически докерфайл — набор консольных команд, нужных, чтобы получить из базового образа требуемый, если уж «утрировать». Собственно, мне и кажется удивительным, когда человек считает, что собрать последовательность команд в файл с определенной структуры — это сложнее, чем ручками единоразово вбить ровно те же команды в консоли, попутно ЧИТАЯ, что там внутри происходит, и не упало ли чего. Т.е. мотивация LXD-сложна, говно?

А на выходе мы имеем докерфайл, НЕ предназначенный для пересборки по необходимости. Он предназначен для того, чтобы один раз собрать образ и мутить с ним, и быть очень-очень осторожным с ключами --force-rebuild. Вот это НЕ то, для чего докер предназначен.

Ну вот СУБД ПЛОХО, ИЗ РУК ВОН ПЛОХО в философию докера ложатся. А в философию «а мы рядом еще и приложение положим» — это вообще писец.
Собственно, мне и кажется удивительным, когда человек считает, что собрать последовательность команд в файл с определенной структуры — это сложнее, чем ручками единоразово вбить ровно те же команды в консоли, попутно ЧИТАЯ, что там внутри происходит, и не упало ли чего.

А если потом нужно изменить изменить седьмую команду из двадцати? Остальные 19 заново вводить? Ну или, в лучшем случае, 12?

Ну или, в лучшем случае, 12?


Какой такой арифметикой у вас 12 получилось?

Вы вот одну важную штуку скажите: в докерфайле как-то можно изменить 7-ю команду из 20 так, чтобы последующие 13 на автомате не перезапустились?

Вот вам совершенно «в лоб» кейс: тупое обновление файла с часовыми поясами в контейнере (а информация о часовых поясах, скорее всего, в базовый контейнер входит) вызывает переустановку СУБД поверх живых данных. Возможно, еще и с инициализацией. Гениально, вам не кажется?

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

В контейнере ОС вы можете «накатить патчик» и заснапшотить новое состояние. В контейнере приложения — только пересборка, только хардкор. СУБД очень не любят, когда их переустанавливают.

И это простейший случай. Я не говорю о тех случаях, когда окромя СУБД, сопсна, приложухе понадобился какой-нибудь редис, монга или кафка. Вы и их в контейнер упаковывать будете? Чтобы при обновлении версии монги у вас, на всякий случай, постгре переустанавливался? Вы же себя разработчиком называете, вы же должны были слышать про декомпозицию, нахрена вы хардкодите это гомно?

При деплое нет никакого докерфайла, есть контейнер, чОрная коробка такая, и никто не знает, предположительно, что у нее внутри. Поэтому dockerfile — это часть ИСХОДНОГО ТЕКСТА программы, куда вы захардкодили локальные пути к файлам и линк к СУБД. При этом вы продолжаете уверять окружающих, что это нормально, и вообще вы хороший разработчик.
Есть.
Докер — контейнер приложения.
LXD — контейнер ОС.
Касательно п.10 — начали за здравие и кончили за упокой. Таким образом очень быстро приходим к необходимости service discovery, которого в docker изначально нет. Либо изворачиваться с внешними решениями, которые инкапсулируешь к себе в контейнер (consul, например), либо резко перекатываться в кубик и использовать его возможности (но тоже не абсолют).
в docker есть встроенный кластерный оркестратор в том числе с service discovery — swarm. Возможностей (судя по описаниям k8s) поменьше, ограничений побольше, но гораздо-гораздо проще, если вам не нужна оркестрация тысячами контейнеров только в прод окружении, автоскейлинг и прочие мастхэв плюшки хайлоада, ентерпрайза и т. п., а просто нужно CI/CD приложения на пару десятков сервисов. Да даже чего-то вроде бложика на вордпресс.
Это такое… Все равно эти доменные имена надо где-то регистрировать, чтобы сервис-потребитель мог найти сервис-поставщика. В частности, проблема с сервисами типа nginx, который если DNS апстрима не резолвится, вообще стартовать не будет. Это все можно обойти перестроив свое мышление и архитектуру приложения(й), но это требует времени, внимания и усилий.
Как-то особо не сталкивался с глобальной перестройкой мышления пока просто контейнеризируешь относительно простые приложения с условно стандартной архитектурой, которые до того раскатывались по серверам ручками по пускай объёмной, но простой инструкции. Единственная более-менее серьёзная проблема — отзыв контейнеров на запросы внешних клиентов, вернее донесение до них IP публичного адреса контейнера (обычно контейнера с прокси).

Перестройка мышления начинается немного позже, когда хочется использовать возможности, которые контейнеризация обещает достигать гораздо проще чем при классическом деплое. Отказоустойчивость, масштабирование и т. п.
Посоветуйте что почитать про контейнеру эникейщику-админу? Везде про использование в разработке… А то дальше запуска собранных другими контейнеров не заходил, становится стыдно. Книжку или цикл статей. Книжку, пожалуй, лучше.
И лучше вообще не запускать stateful приложения в контейнерах
Коллеги, видим, что тема задела. Приглашаем всех через неделю на Red Hat Forum Russia 2018 – будет возможность задать вопросы напрямую инженерам Red Hat.
Спасибо за ссылочку!!!
Sign up to leave a comment.