Трудно представить современную разработку без контейнеризации. Docker и Kubernetes прочно обосновались на рынке, и, если вы ещё не знакомы с этими технологиями, им явно стоит уделить внимание.
Запуск баз данных и других stateful приложений в контейнере – это тема интересная, но способная вызвать очередной Большой взрыв в комментариях. Оговорюсь сразу, мы не используем в production окружении PostgreSQL в Docker. Но делаем это в локальной разработке и на dev-стендах. Почему? Потому что это чертовски удобно!
В этой статье я хочу рассмотреть типовые способы запуска ванильного (то есть чистого/оригинального) PostgreSQL в контейнере, а также проблемы и их возможные решения, с которыми может столкнуться software engineer. Статья задумывалась как небольшое руководство для новых ребят, приходящих в мою команду, но, уверен, будет полезна и более широкой аудитории.
Прежде чем мы начнём
Вам понадобится Docker на машине, где вы будете проводить эксперименты. Скачайте его с официального сайта и установите. Настоятельно рекомендуется использовать актуальную версию.
Все приведенные в этой статье команды и скрипты запускались на версии Docker Desktop 3.5.2 и выше. Их работоспособность на старых версиях Docker не гарантируется.
Так же подразумевается, что у вас есть базовые навыки работы с Docker. Если ещё нет, то для начала крайне желательно ознакомиться со статьями один и два.
Где взять образы PostgreSQL?
Официальные образы PostgreSQL опубликованы на Docker Hub. Там же можно найти базовые инструкции по использованию этих образов. Я буду опираться в том числе и на них.
Hello Postgres
Официальный образ Постгреса очень продвинутый и позволяет настраивать множество параметров. Для быстрого старта большинство из них можно оставить как есть, но вот пароль суперпользователя придётся задать явно:
docker run --name habr-pg -e POSTGRES_PASSWORD=pgpwd4habr -d postgres
Эта команда запустит нам контейнер PostgreSQL в фоновом (detached) режиме и присвоит ему имя habr-pg:
Классно, не правда ли? А что мы можем делать с этой базой данных? К сожалению, на текущий момент не так уж и много. Через интерфейс Docker можно запустить CLI, подключиться к контейнеру и уже оттуда запустить, например, psql:
psql --username=postgres --dbname=postgres
Далее я буду использовать сокращенный вариант этой команды:
psql -U postgres -d postgres
И тут мы сталкиваемся с первой проблемой: что вернёт нам запрос select version();
, выполненный в консоли? Мы не указали явным образом версию БД, которую хотим использовать. Давайте это исправим:
docker run --name habr-pg-13.3 -e POSTGRES_PASSWORD=pgpwd4habr -d postgres:13.3
Теперь вопросов об используемой версии БД не возникает, но работать с ней по-прежнему не очень удобно. Нам нужно сделать эту БД доступной извне, чтобы к ней могли подключаться приложения и IDE. Для этого нужно выставить наружу порт:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_PASSWORD=pgpwd4habr -d postgres:13.3
Отлично! С этого момента к базе данных можно подключиться, например, из IntelliJ IDEA:
Сейчас мы используем пользователя и базу данных в контейнере, создаваемых по умолчанию, я же предпочитаю указывать их явно. Финальная версия команды для запуска будет иметь вид:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_USER=habrpguser -e POSTGRES_PASSWORD=pgpwd4habr -e POSTGRES_DB=habrdb -d postgres:13.3
psql можно запустить так: psql -U habrpguser -d habrdb
И соответствующий compose-файл:
version: "3.9"
services:
postgres:
image: postgres:13.3
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
ports:
- "5432:5432"
Инициализация структуры БД
К текущему моменту мы научились запускать в контейнере необходимую нам версию PostgreSQL, переопределять суперпользователя и создавать базу данных с нужным именем.
Это хорошо, но чистая база данных вряд ли будет сильно полезна. Для работы/тестов/экспериментов нужно наполнить эту базу таблицами и другими объектами. Разумеется, всё это можно сделать вручную, но, согласитесь, гораздо удобнее, когда сразу после запуска вы автоматически получаете полностью готовую БД.
Разработчики официального образа PostgreSQL естественно предусмотрели этот момент и предоставили нам специальную точку входа для инициализации базы данных - docker-entrypoint-initdb.d. Любые *.sql или *.sh файлы в этом каталоге будут рассматриваться как скрипты для инициализации БД. Здесь есть несколько нюансов:
если БД уже была проинициализирована ранее, то никакие изменения к ней применяться не будут;
если в каталоге присутствует несколько файлов, то они будут отсортированы по имени с использованием текущей локали (по умолчанию en_US.utf8).
Инициализацию БД можно запустить через однострочник, но в этом случае требуется указывать абсолютный путь до каталога со скриптами:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_USER=habrpguser -e POSTGRES_PASSWORD=pgpwd4habr -e POSTGRES_DB=habrdb -d -v "/absolute/path/to/directory-with-init-scripts":/docker-entrypoint-initdb.d postgres:13.3
Например, на моей машине это выглядит так:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_USER=habrpguser -e POSTGRES_PASSWORD=pgpwd4habr -e POSTGRES_DB=habrdb -d -v "/Users/ivahrusev/src/useful-sql-scripts/running_pg_in_docker/2. Init Database":/docker-entrypoint-initdb.d postgres:13.3
В качестве обходного варианта можно использовать макрос, на лету определяя рабочую директорию, и запускать команду из каталога со скриптами:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_USER=habrpguser -e POSTGRES_PASSWORD=pgpwd4habr -e POSTGRES_DB=habrdb -d -v "$(pwd)":/docker-entrypoint-initdb.d postgres:13.3
Использование docker-compose файла в этом случае более удобно и позволяет указывать относительные пути:
version: "3.9"
services:
postgres:
image: postgres:13.3
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
volumes:
- .:/docker-entrypoint-initdb.d
ports:
- "5432:5432"
Здесь хотелось бы акцентировать ваше внимание на одной простой вещи, о которой уже говорил в предыдущей статье: при создании миграций БД для ваших приложений отдавайте предпочтение чистому (plain) SQL. В этом случае их можно будет переиспользовать с минимальными затратами.
А куда сохраняются мои данные?
Базы данных – это в первую очередь история про персистентность. И,.. Хьюстон, кажется у нас проблема… К настоящему моменту мы никак не управляем долговременным хранением нашей базы данных. Эту задачу целиком на себя берёт Docker, автоматически создавая volume для контейнера с БД. Есть целый ворох причин, почему это плохо, начиная от банальной невозможности просматривать содержимое volume’ов в бесплатной версии Docker Desktop и заканчивая лимитами дискового пространства.
Разумеется, хорошей практикой является полностью ручное управление физическим размещением создаваемых баз данных. Для этого нам нужно подмонтировать соответствующий каталог (куда будут сохраняться данные) в контейнер и при необходимости переопределить переменную окружения PGDATA:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_USER=habrpguser -e POSTGRES_PASSWORD=pgpwd4habr -e POSTGRES_DB=habrdb -e PGDATA=/var/lib/postgresql/data/pgdata -d -v "/absolute/path/to/directory-with-data":/var/lib/postgresql/data -v "/absolute/path/to/directory-with-init-scripts":/docker-entrypoint-initdb.d postgres:13.3
Вариант с макросом, использующий для инициализации БД скрипты из предыдущего раздела:
docker run --name habr-pg-13.3 -p 5432:5432 -e POSTGRES_USER=habrpguser -e POSTGRES_PASSWORD=pgpwd4habr -e POSTGRES_DB=habrdb -e PGDATA=/var/lib/postgresql/data/pgdata -d -v "$(pwd)":/var/lib/postgresql/data -v "$(pwd)/../2. Init Database":/docker-entrypoint-initdb.d postgres:13.3
С однострочниками на этом закончим. Все дальнейшие шаги будем осуществлять только через compose-файл:
version: "3.9"
services:
postgres:
image: postgres:13.3
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5432:5432"
При запуске этого скрипта рядом с ним создастся директория pgdata, где будут располагаться файлы БД.
Healthcheck? Нет, не слышал…
Проверка состояния/работоспособности – healthcheck – вполне устоявшийся архитектурный шаблон, который вы должны взять на вооружение для всех ваших приложений. База данных, запускаемая в контейнере, не является исключением.
Основная задача healthcheck’а – как можно скорее уведомить среду, управляющую контейнером, о том, что с контейнером что-то не так. И самая простая стратегия решения проблемы – перезапуск контейнера.
Так же стоит сразу позаботиться об ограничении ресурсов для контейнера с БД. Для экспериментов и локального запуска вполне подойдёт секция resources (флаг --compatibility больше не требуется).
Healthcheck для PostgreSQL обычно основывается на использовании утилиты pg_isready как показано ниже:
version: "3.9"
services:
postgres:
image: postgres:13.3
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U habrpguser -d habrdb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 4G
А если хочу изменить параметры БД?
Для администраторов PostgreSQL не секрет, что конфигурация СУБД из коробки далека от идеальной и не очень подходит для эксплуатации. Я немного рассказывал об этом в своей статье про pg-index-health: ряд параметров нужно изменить в обязательном порядке, так как они влияют на производительность. Так же существует большое количество расширений для Постгреса, которые сделают эксплуатацию БД более удобной, наблюдаемой и управляемой. Одно из таких расширений - pg_stat_statements (кстати, оно пригодится нам позднее для мониторинга БД).
Ванильный образ PostgreSQL позволяет тюнить параметры и добавлять расширения на старте контейнера БД:
version: "3.9"
services:
postgres:
image: postgres:13.3
command:
- "postgres"
- "-c"
- "max_connections=50"
- "-c"
- "shared_buffers=1GB"
- "-c"
- "effective_cache_size=4GB"
- "-c"
- "work_mem=16MB"
- "-c"
- "maintenance_work_mem=512MB"
- "-c"
- "random_page_cost=1.1"
- "-c"
- "temp_file_limit=10GB"
- "-c"
- "log_min_duration_statement=200ms"
- "-c"
- "idle_in_transaction_session_timeout=10s"
- "-c"
- "lock_timeout=1s"
- "-c"
- "statement_timeout=60s"
- "-c"
- "shared_preload_libraries=pg_stat_statements"
- "-c"
- "pg_stat_statements.max=10000"
- "-c"
- "pg_stat_statements.track=all"
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U habrpguser -d habrdb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 4G
Разумеется, можно указать свой postgresql.conf. Оставлю это в качестве домашнего задания.
Посмотреть список установленных расширений можно с помощью запроса select * from pg_extension;
.
А команда show позволит узнать текущее значение того или иного параметра, например: show random_page_cost;
.
Не люблю консоль; дайте мне человеческий UI!
Далеко не все пользователи любят работать с БД из командной строки. Очень многие предпочитают использовать для этого продвинутый графический интерфейс, например pgAdmin.
Запустить ещё один контейнер, в котором будет бежать GUI, не сложно, но для удобной коммуникации с БД их лучше объединить в одну сеть:
version: "3.9"
services:
postgres:
container_name: postgres_container
image: postgres:13.3
command:
- "postgres"
- "-c"
- "max_connections=50"
- "-c"
- "shared_buffers=1GB"
- "-c"
- "effective_cache_size=4GB"
- "-c"
- "work_mem=16MB"
- "-c"
- "maintenance_work_mem=512MB"
- "-c"
- "random_page_cost=1.1"
- "-c"
- "temp_file_limit=10GB"
- "-c"
- "log_min_duration_statement=200ms"
- "-c"
- "idle_in_transaction_session_timeout=10s"
- "-c"
- "lock_timeout=1s"
- "-c"
- "statement_timeout=60s"
- "-c"
- "shared_preload_libraries=pg_stat_statements"
- "-c"
- "pg_stat_statements.max=10000"
- "-c"
- "pg_stat_statements.track=all"
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U habrpguser -d habrdb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 4G
networks:
- postgres
pgadmin:
container_name: pgadmin_container
image: dpage/pgadmin4:5.7
environment:
PGADMIN_DEFAULT_EMAIL: "habrpguser@habr.com"
PGADMIN_DEFAULT_PASSWORD: "pgadminpwd4habr"
PGADMIN_CONFIG_SERVER_MODE: "False"
volumes:
- ./pgadmin:/var/lib/pgadmin
ports:
- "5050:80"
restart: unless-stopped
deploy:
resources:
limits:
cpus: '0.5'
memory: 1G
networks:
- postgres
networks:
postgres:
driver: bridge
pgAdmin стартует на порту 5050: перейдя на нужный адрес, можно будет настроить подключение к БД.
А как насчёт мониторинга?
В современной разработке любой микросервис или инфраструктурный компонент должен быть поставлен на мониторинг, то есть непрерывно отдавать метрики - ключевые показатели, позволяющие определить, как ведёт себя система в данный момент времени.
PostgreSQL не имеет встроенной интеграции с системами мониторинга наподобие Prometheus (или Zabbix). Вместо этого он полагается на использование внешних агентов - экспортеров. Мы у себя активно используем postgres_exporter, позволяющий добавлять свои собственные sql-запросы и кастомные метрики на их основе:
version: "3.9"
services:
postgres:
container_name: postgres_container
image: postgres:13.3
command:
- "postgres"
- "-c"
- "max_connections=50"
- "-c"
- "shared_buffers=1GB"
- "-c"
- "effective_cache_size=4GB"
- "-c"
- "work_mem=16MB"
- "-c"
- "maintenance_work_mem=512MB"
- "-c"
- "random_page_cost=1.1"
- "-c"
- "temp_file_limit=10GB"
- "-c"
- "log_min_duration_statement=200ms"
- "-c"
- "idle_in_transaction_session_timeout=10s"
- "-c"
- "lock_timeout=1s"
- "-c"
- "statement_timeout=60s"
- "-c"
- "shared_preload_libraries=pg_stat_statements"
- "-c"
- "pg_stat_statements.max=10000"
- "-c"
- "pg_stat_statements.track=all"
environment:
POSTGRES_DB: "habrdb"
POSTGRES_USER: "habrpguser"
POSTGRES_PASSWORD: "pgpwd4habr"
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U habrpguser -d habrdb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 4G
networks:
- postgres
pgadmin:
container_name: pgadmin_container
image: dpage/pgadmin4:5.7
environment:
PGADMIN_DEFAULT_EMAIL: "habrpguser@habr.com"
PGADMIN_DEFAULT_PASSWORD: "pgadminpwd4habr"
PGADMIN_CONFIG_SERVER_MODE: "False"
volumes:
- ./pgadmin:/var/lib/pgadmin
ports:
- "5050:80"
restart: unless-stopped
deploy:
resources:
limits:
cpus: '0.5'
memory: 1G
networks:
- postgres
postgres_exporter:
container_name: exporter_container
image: prometheuscommunity/postgres-exporter:v0.10.0
environment:
DATA_SOURCE_URI: "postgres:5432/habrdb?sslmode=disable"
DATA_SOURCE_USER: "habrpguser"
DATA_SOURCE_PASS: "pgpwd4habr"
PG_EXPORTER_EXTEND_QUERY_PATH: "/etc/postgres_exporter/queries.yaml"
volumes:
- ./queries.yaml:/etc/postgres_exporter/queries.yaml:ro
ports:
- "9187:9187"
restart: unless-stopped
deploy:
resources:
limits:
cpus: '0.2'
memory: 500M
networks:
- postgres
networks:
postgres:
driver: bridge
После запуска скрипта экспортер будет доступен на порту 9187 и отдавать метрики в формате Prometheus:
...
# HELP pg_stat_user_tables_n_tup_upd Number of rows updated
# TYPE pg_stat_user_tables_n_tup_upd counter
pg_stat_user_tables_n_tup_upd{datname="habrdb",relname="first_table",schemaname="public",server="postgres:5432"} 0
pg_stat_user_tables_n_tup_upd{datname="habrdb",relname="second_table",schemaname="public",server="postgres:5432"} 0
# HELP pg_stat_user_tables_seq_scan Number of sequential scans initiated on this table
# TYPE pg_stat_user_tables_seq_scan counter
pg_stat_user_tables_seq_scan{datname="habrdb",relname="first_table",schemaname="public",server="postgres:5432"} 1
pg_stat_user_tables_seq_scan{datname="habrdb",relname="second_table",schemaname="public",server="postgres:5432"} 1
# HELP pg_stat_user_tables_seq_tup_read Number of live rows fetched by sequential scans
# TYPE pg_stat_user_tables_seq_tup_read counter
pg_stat_user_tables_seq_tup_read{datname="habrdb",relname="first_table",schemaname="public",server="postgres:5432"} 0
pg_stat_user_tables_seq_tup_read{datname="habrdb",relname="second_table",schemaname="public",server="postgres:5432"} 0
# HELP pg_stat_user_tables_vacuum_count Number of times this table has been manually vacuumed (not counting VACUUM FULL)
# TYPE pg_stat_user_tables_vacuum_count counter
pg_stat_user_tables_vacuum_count{datname="habrdb",relname="first_table",schemaname="public",server="postgres:5432"} 0
pg_stat_user_tables_vacuum_count{datname="habrdb",relname="second_table",schemaname="public",server="postgres:5432"} 0
# HELP pg_static Version string as reported by postgres
# TYPE pg_static untyped
pg_static{server="postgres:5432",short_version="13.3.0",version="PostgreSQL 13.3 (Debian 13.3-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit"} 1
...
Разумеется, для полноценной постановки на мониторинг нужно ещё поднять сам Prometheus + Grafana, а так же загрузить подходящий dashboard, но это уже выходит за рамки данной статьи. Более того, если ваша служба информационной безопасности исповедует Zero Trust, то экспортер придётся прикрыть с помощью nginx и настроить mTLS...
В качестве заключения
На этом у меня всё. Приведенной выше конфигурации более чем достаточно для развёртывания БД PostgreSQL в Docker-контейнере на стенде разработки или локально.
Все приведённые в статье команды и docker-compose файлы также доступны на GitHub.
Комментарии (29)
Hivemaster
20.09.2021 08:58+2А здесь DBA и контрибьютор постгреса пишет, что контейнеризация СУБД - это плохая идея. Что на это скажите?
Roman_Cherkasov
20.09.2021 09:07+4Я не уверен на счет использования бд в контейнере на проде, но контейнеризация бд очень удобна во время разработки. В частности, можно сделать образы баз с уже заполненными тестовыми данными и не стесняясь - ломать их (потому что развернуть контейнер снова - быстрее чем заполнять базу из csv или какими бы то небыло скриптами.) Или например после тестирования автоматически удалять контейнеры и так далее.
DarkSavant
20.09.2021 10:41+2Вот именно.
В статье вроде и указано, что для дев или тест.
И да, на мой взгляд, для разработки и тестов контейнеры божественны. В проде иногда тоже использую, но не для СУБД.
bvg1962kam
20.09.2021 11:46Я плотно использовал БД на проде в docker контейнерах, правда mysql и mongodb. Проблем вообще нет, полет нормальный. Да, есть небольшие отличия от простой установки, но если знать основные команды работы с docker, привыкаешь и через неделю забываешь обо всех отличиях. Спасибо за статью!
apapacy
20.09.2021 13:08Могу подтвердить так как испольшовнаие ктнтейнера на проде привело один раз к разрушению базы данных, после этого больше нет желания повторить опыт.
Sigest
21.09.2021 07:12+1А можете поподробнее? В статье указано, что файлы самой бд пишутся в расшаренные папки. Ну допустим бд упала. Что мешает поднять заново контейнер и приатачить эти же папки туда? Спрашиваю потому что сам использую бд, да и вообще все сервисы в докерах на пет проектах и инцидентов пока не было. Но я разработчик, а не DBA и мне просто любопытно
vodopad
04.10.2021 20:22У нас был жёсткий human error: надо было создать ещё одну базу на Postgres. Решили поднять ещё один инстанс (это же docker, новая БД должна была быть маленькой и нетребовательной к ресурсам, типа docker-way), а не просто создать новую БД в существующем СУБД (как бы мы сделали на StanAlone), И один человек увлёкся копипастом в docker-compose и замонтировал один и тот же volume и на новую БД, и на старую. И обе БД в итоге пострадали.
Поэтому надо быть осторожнее.
ihost
20.09.2021 10:50+1Абсолютно поддерживаю: зачем вообще запускать RDBMS в контейнерах, ведь единственное что можно получить - снижение производительности и падение fault tolerance?! Сколько раз приходилось сталкиваться с ситуацией, когда кто-то запускал RDBMS в каких-нибудь условных кубах, и потом жаловался, что приложение (использующее базу) работает очень медленно и нестабильно, посколько время выполнения SQL-запросов падает даже не в разы, а на порядок-два
Удивительно, что не видать нигде ни в открытом доступе, ни в виде коммерческого решения связи из какой-нибудь хорошей RDBMS вроде Postgres и DPDK (Home - DPDK), чтобы запускать базу сразу на нативном сетевом интерфейсе без огромного оверхеда на TCP/IP-стек ядра и тонны системных вызовов с переключением контекстов - на основе так называемого Poll Mode Driver
ReDev1L
21.09.2021 00:30+2Откуда вы это берёте? В кубах на СУБД не используются PVC и Ceph. Волюмы пробрасывают на хосты. Получаются отличные HA FT кластера СУБД с быстрой автоматической раскаткой.
С 2016 года использую разные СУБД в докере и кубере, все отказы которые встречали - никак не были связаны с докером. Не было и нету никаких оверхедов (я готов не считать до 3% на оверхед, за такие удобства) при нормальной настройке кластеров / хостов.
IvanVakhrushev Автор
20.09.2021 11:50+2На самом деле здесь нет правильного ответа. И категорично что-то утверждать будет неправильно. Как и всегда, всё зависит от вашей специфики и нагрузки.
Если у вас большая нагруженная БД, то тащить её в контейнер не очень разумно.
Если у вас микросервисы и вам требуется небольшая БД на 5-10 TPS, то почему нет?
Stormwalker
20.09.2021 12:13Хороший материал, хотелось бы еще узнать, как быть в ситуации, где приложению необходимо для старта дождаться ответа базы
IvanVakhrushev Автор
20.09.2021 13:00У меня нет готового примера/кусочка кода, который можно было бы показать, но себя в Kubernetes/OpenShift мы используем следующий подход:
1) в deployment добавляем соответствующий init-container, в котором дожидаемся доступности БД (цикл, ограниченный по времени и числу итераций);
2) в readiness пробе проверяем доступность БД (select 1, например).Сначала стартует init-контейнер и проверяет доступна ли БД, если нет то уходит в ожидание на какое-то время, после чего снова повторяет проверку. И так несколько раз (все параметры настраиваются).
Затем уже приложение у себя в readiness пробе проверяет доступность БД (перестраховка по сути, можно отказаться от этого).
Isaac_ods
20.09.2021 17:33Почитал ответ dba постгреса про минусы контейнеризации бд в проде. Но что делать, если на одной машине надо запустить несколько проектов с несколькими бд? В одном постгресе создавать несколько баз с разными юзерами и правами?
Вообще вопрос "почему докеризация бд в проде - плохая идея" сидел в голове, но пока я на практике не дошел до решения этого вопроса, то и не гуглил, так что спасибо за комменты выше
Stalker_RED
20.09.2021 19:12Вы так говорите, будто разные юзеры с разными правами, это что-то сложное или плохое.
Isaac_ods
20.09.2021 20:54Для полноты картины (я не девопс) - изучаю для себя деплой двух разных пет проектов на сервере хетцнера через ansible и автоматизировать добавление новых контейнеров с новой бд мне пока видится легче, чем автоматизировать добавление новых бд и юзеров
Stalker_RED
21.09.2021 14:04добавление БД и юзера это 3-4 консольных команд
https://www.a2hosting.com/kb/developer-corner/postgresql/managing-postgresql-databases-and-users-from-the-command-line
и еще одна, чтобы залить схему или дамп в эту БД.
lurker
21.09.2021 10:29Можно поднять еще один кластер postgres, возможно даже другой версии, если требуется
taluyev
25.09.2021 02:07Использую майскл на проде в докере. После перезагрузки vps сервера база умерла. не разбирался с причиной, просто восстановил из полного ежедневного архива. База маленькая и пополняется не очень часто. База в докере - это возможность держать несколько проектов на одном вэпээс сервере, мне очень нравится такой подход. В случае большой базы, да можно подумать прежде чем так делать.
ScarferNV
24.09.2021 22:07В качестве игрушки пойдет. Но не более. Регресс тестирование тоже на контейнерах проводите?
vodopad
04.10.2021 20:28А можете сказать, почему не лучше замонтировать postgres.conf внутрь контейнера, чем городить такую "простыню" в docker-compose с передачей опций запуска БД (-c)?
IvanVakhrushev Автор
07.10.2021 09:45Согласен, что такой подход получается многословным, но он наглядный. Для учебных целей подходит гораздо лучше.
tmk826
Скорее docker туториал на примере postgresql.