Бази даних

Робота з PostgreSQL в нашій інфраструктурі — підключення, адміністрування, бекапи.

PostgreSQL основи

Підключення до контейнера

# Вхід в контейнер postgres
docker exec -it postgres bash

# Або одразу запустити psql
docker exec -it postgres psql -U postgres

Основні psql команди

-- Список всіх баз даних
\l

-- Підключитися до бази
\c database_name

-- Список таблиць
\dt

-- Структура таблиці
\d table_name

-- Список користувачів
\du

-- Вихід
\q

Корисні запити

-- Розмір бази даних
SELECT pg_size_pretty(pg_database_size('database_name'));

-- Розмір таблиць
SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename::text))
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(tablename::text) DESC;

-- Активні з'єднання
SELECT * FROM pg_stat_activity WHERE datname = 'database_name';

-- Кількість з'єднань по базах
SELECT datname, count(*) FROM pg_stat_activity GROUP BY datname;

Створення бази та користувача

-- Створити користувача
CREATE USER service_user WITH PASSWORD 'secure_password';

-- Створити базу
CREATE DATABASE service_db OWNER service_user;

-- Надати всі права на базу
GRANT ALL PRIVILEGES ON DATABASE service_db TO service_user;

-- Підключитись до бази та надати права на схему
\c service_db
GRANT ALL ON SCHEMA public TO service_user;

Наші бази даних

MAS (Matrix Authentication Service)

docker exec -it postgres psql -U postgres -d mas

Основні таблиці:

Таблиця Опис
users Облікові записи користувачів
user_emails Email адреси користувачів
user_sessions Активні сесії
oauth2_sessions OAuth сесії
upstream_oauth_links Зв'язки з upstream провайдерами
-- Переглянути користувачів
SELECT id, username, created_at FROM users;

-- Активні сесії
SELECT u.username, s.created_at, s.last_active_at
FROM user_sessions s
JOIN users u ON s.user_id = u.id
WHERE s.finished_at IS NULL;

-- Заблокувати користувача
UPDATE users SET locked_at = NOW() WHERE username = 'user_to_lock';

Synapse (Matrix Server)

docker exec -it postgres psql -U postgres -d synapse

Основні таблиці:

Таблиця Опис
users Matrix користувачі
rooms Кімнати
events Всі події (повідомлення, стани)
room_memberships Членство в кімнатах
devices Пристрої користувачів
-- Користувачі
SELECT name, creation_ts, is_guest, admin FROM users;

-- Кімнати з кількістю учасників
SELECT r.room_id, r.creator, COUNT(m.user_id) as members
FROM rooms r
LEFT JOIN room_memberships m ON r.room_id = m.room_id AND m.membership = 'join'
GROUP BY r.room_id, r.creator;

-- Зробити користувача адміном
UPDATE users SET admin = 1 WHERE name = '@user:eliah.one';

Wiki

docker exec -it postgres psql -U postgres -d wiki

База метаданих для wiki — сесії, кеш, статистика.

Planka

docker exec -it postgres psql -U postgres -d planka

Kanban дошки — проєкти, картки, користувачі.

Nextcloud

docker exec -it postgres psql -U postgres -d nextcloud

Файлове сховище — користувачі, файли, shares.

Додавання нового сервісу

1. Створення бази та користувача

docker exec -it postgres psql -U postgres
-- Створити користувача для сервісу
CREATE USER myservice WITH PASSWORD 'generated_secure_password';

-- Створити базу
CREATE DATABASE myservice OWNER myservice;

-- Надати права
GRANT ALL PRIVILEGES ON DATABASE myservice TO myservice;

\c myservice
GRANT ALL ON SCHEMA public TO myservice;

2. Docker Compose конфігурація

services:
  myservice:
    image: myservice:latest
    environment:
      - DATABASE_URL=postgresql://myservice:password@postgres:5432/myservice
      # Або окремі змінні
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_NAME=myservice
      - DB_USER=myservice
      - DB_PASSWORD=${MYSERVICE_DB_PASSWORD}
    networks:
      - internal
    depends_on:
      - postgres

networks:
  internal:
    external: true

3. Environment variables (.env)

# Додати в .env файл
MYSERVICE_DB_PASSWORD=your_secure_password_here

4. Приклад для Python (SQLAlchemy)

import os
from sqlalchemy import create_engine

DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL)

5. Приклад для Node.js (pg)

const { Pool } = require('pg');

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

Особливості інфраструктури

Shared PostgreSQL

Всі сервіси використовують один PostgreSQL контейнер з окремими базами:

postgres (контейнер)
├── mas (база)
├── synapse (база)
├── wiki (база)
├── planka (база)
└── nextcloud (база)

Переваги:
- Менше ресурсів
- Простіше бекапити
- Єдина точка конфігурації

Недоліки:
- Single point of failure
- Спільні ресурси

Docker мережа

Сервіси підключаються до postgres через внутрішню Docker мережу:

Host: postgres (ім'я контейнера)
Port: 5432

Не використовуйте localhost — це буде вказувати на сам контейнер сервісу.

Connection string формат

postgresql://user:password@host:port/database

# Приклади
postgresql://mas:password@postgres:5432/mas
postgresql://synapse:password@postgres:5432/synapse

З додатковими параметрами:

postgresql://user:password@postgres:5432/database?sslmode=disable&connect_timeout=10

Права доступу (GRANT)

-- Повні права на базу
GRANT ALL PRIVILEGES ON DATABASE dbname TO username;

-- Права на існуючі таблиці
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO username;

-- Права на майбутні таблиці
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO username;

-- Тільки читання
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;

Backup та Restore

Бекап однієї бази

# З контейнера
docker exec postgres pg_dump -U postgres -d database_name > backup.sql

# Стиснутий бекап
docker exec postgres pg_dump -U postgres -Fc database_name > backup.dump

Бекап всіх баз

docker exec postgres pg_dumpall -U postgres > all_databases.sql

Restore

# З SQL файлу
docker exec -i postgres psql -U postgres -d database_name < backup.sql

# З dump файлу
docker exec -i postgres pg_restore -U postgres -d database_name < backup.dump

# Створити базу та відновити
docker exec -i postgres createdb -U postgres new_database
docker exec -i postgres pg_restore -U postgres -d new_database < backup.dump

Автоматизація через cron

Створіть скрипт /opt/scripts/backup-postgres.sh:

#!/bin/bash
BACKUP_DIR="/opt/backups/postgres"
DATE=$(date +%Y-%m-%d_%H-%M)
RETENTION_DAYS=7

# Бекап кожної бази
for DB in mas synapse wiki planka nextcloud; do
    docker exec postgres pg_dump -U postgres -Fc $DB > "$BACKUP_DIR/${DB}_${DATE}.dump"
done

# Видалити старі бекапи
find $BACKUP_DIR -name "*.dump" -mtime +$RETENTION_DAYS -delete

echo "Backup completed: $DATE"

Додати в crontab:

# Щодня о 3:00
0 3 * * * /opt/scripts/backup-postgres.sh >> /var/log/postgres-backup.log 2>&1

Перевірка бекапів

# Перевірити що файл не порожній
ls -lh /opt/backups/postgres/

# Перевірити вміст dump
docker exec -i postgres pg_restore -l < backup.dump

# Тестове відновлення в тимчасову базу
docker exec postgres createdb -U postgres test_restore
docker exec -i postgres pg_restore -U postgres -d test_restore < backup.dump
docker exec postgres dropdb -U postgres test_restore

Troubleshooting

Connection refused

# Перевірити чи запущений контейнер
docker ps | grep postgres

# Перевірити логи
docker logs postgres

# Перевірити чи слухає порт
docker exec postgres pg_isready -U postgres

Можливі причини:
- Контейнер не запущений
- Неправильний hostname (використовуйте postgres, не localhost)
- Контейнери в різних мережах

Authentication failed

# Перевірити користувача
docker exec -it postgres psql -U postgres -c "\du"

# Скинути пароль
docker exec -it postgres psql -U postgres -c "ALTER USER username WITH PASSWORD 'new_password';"

Можливі причини:
- Неправильний пароль
- Користувач не існує
- Користувач не має прав на базу

Too many connections

# Перевірити кількість з'єднань
docker exec -it postgres psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;"

# Побачити активні з'єднання
docker exec -it postgres psql -U postgres -c "SELECT pid, usename, datname, state, query_start FROM pg_stat_activity;"

# Завершити idle з'єднання
docker exec -it postgres psql -U postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle' AND query_start < NOW() - INTERVAL '1 hour';"

Збільшити ліміт в postgresql.conf:

max_connections = 200

Disk full

# Перевірити використання диску
docker exec postgres df -h /var/lib/postgresql/data

# Розмір баз
docker exec -it postgres psql -U postgres -c "SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database ORDER BY pg_database_size(datname) DESC;"

# Очистити WAL логи (обережно!)
docker exec postgres pg_controldata /var/lib/postgresql/data | grep "Latest checkpoint"

Рішення:
- Видалити старі бекапи
- Очистити великі таблиці
- Збільшити диск

Повільні запити

# Увімкнути логування повільних запитів
docker exec -it postgres psql -U postgres -c "ALTER SYSTEM SET log_min_duration_statement = 1000;"
docker exec -it postgres psql -U postgres -c "SELECT pg_reload_conf();"

# Переглянути активні запити
docker exec -it postgres psql -U postgres -c "SELECT pid, now() - query_start AS duration, query FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC;"

Корисні аліаси

Додайте в ~/.bashrc:

alias pgcli='docker exec -it postgres psql -U postgres'
alias pgmas='docker exec -it postgres psql -U postgres -d mas'
alias pgsynapse='docker exec -it postgres psql -U postgres -d synapse'
alias pgbackup='docker exec postgres pg_dumpall -U postgres'

Що далі

  • Docker — основи контейнеризації
  • Моніторинг — налаштування алертів
  • Caddy — reverse proxy для сервісів

Шлях: services/databases/overview.md

UMTC Wiki © 2026 | Ukrainian Military Tactical Communications