masha_spb bind после этой пустоты я тоже воткнул, ещё раз бэкапить красивый том без файла желания ноль))
masha_spb писал:
Для sqlite я bind на хост: файл виден, бэкап не пустота.
тут не поспоришь. named
volume сам по себе нормальный, если путь совпадает. у меня не совпал: том на /app/data, база жила в /app/
bot.db, DB_PATH в
env «потом поправлю» и не поправил. контейнер живой, вебхук проходит, история как с нуля. бэкапил том исправно, восстанавливал исправно, на выходе снова пустота. я молодец, полтора часа конфиг крутил и ещё полчаса искал сломанный бэкап, хотя ломал я сам.
сейчас каталог ./data на хосте, в контейнере /app/data, в
env уже /app/data/
bot.db, не /app/
bot.db.
services:
bot:
image: bot:local
restart: unless-stopped
volumes:
- ./data:/app/data
environment:
BOT_TOKEN: ${BOT_TOKEN}
DB_PATH: /app/data/bot.db
OLLAMA_URL: http://127.0.0.1:11434
ALLOW_IDS: ${ALLOW_IDS}
ls ./data/
bot.db — и сразу видно, есть там что-то или снова пусто. это и спасло нервы после первого круга. ещё плюс bind: sqlite3 на хосте видит файл, не надо
docker exec. с named
volume я бы лез в контейнер каждый раз, а sqlite3 в образе бота я даже не ставил, там только
python.
вторая грабля за вечер: контейнер пишет не от
root, папку ./data я создал с хоста своим юзером,
sqlite сразу permission denied.
chown на ./data под uid из контейнера, отпустило. без этого bind тоже выглядит как «том на месте, бот живой, база не пишется», только ошибка уже в логах, не в пустой папке.
бэкап теперь не
docker volume, а файл. тупо
cp ./data/
bot.db пока бот пишет — я так сначала и сделал. у
sqlite есть wal и shm. скопировал один
bot.db, поднял копию на тесте — история обрезанная, последних сообщений нет. копировать три файла руками тоже пробовал, один раз wal не доехал, тестовая база сказала malformed.
живой бот стопать не хочу, вебхук тогда молчит и телега орёт в логах. снимаю слепок через сам
sqlite:
#!/bin/bash
set -euo pipefail
SRC=/home/artem/bots/tg/data/bot.db
DST=/home/artem/bots/tg/backups
mkdir -p "$DST"
STAMP=$(date +%Y%m%d_%H%M)
sqlite3 "$SRC" ".backup '$DST/bot_$STAMP.db'"
find "$DST" -name 'bot_*.db' -mtime +14 -delete
.backup внутри
sqlite консистентный, даже если бот в этот момент пишет. литстрим не трогал, для истории чатов и так хватает. копии лежат рядом с проектом, не внутри ./data. том сгорел — бэкапы живые. бэкапы сгорели — рабочий файл ещё крутится. хранить слепок там же, откуда снимаешь, я уже проверял, проверять больше не буду.
крон на хосте, не в контейнере. в контейнере
cron я год назад поднимал, потом забыл что он там есть, и удивлялся откуда нагрузка.
15 3 * * * /home/artem/bots/tg/backup.sh >> /home/artem/bots/tg/backup.log 2>&1
проверку восстановления делал вечером: контейнер снёс, ./data оставил,
compose up — история на месте, вебхук не перевыпускал. потом отдельно взял вчерашний слепок, подменил
bot.db на тесте — чаты тоже на месте. это уже не «том красивый и пустой».
из гайда путь тома как пример ок, бьёт уже мой
env, который я не довёл до этого пути. кто бэкапит named
volume и не лезет ls внутрь контейнера — гляньте глазами, что файл реально в этом каталоге.
docker volume ls всегда зелёный, это ничего не значит.
bind vs named: для одной
sqlite, которую надо тыкать и копировать, bind. если завтра два сервиса и общая папка — named верну, но с тем же sqlite3 .backup, не
rsync по живому файлу и не «надеюсь путь совпал».
у кого бот с
sqlite в докере — как снимаете, пока контейнер живой? .backup, литстрим, или стопаете на минуту? я стопать не хочу, вебхук тогда 404 ловит.