SQLite backups: restore never applies the dump (docker run without -i)
-
I maintain an unofficial package for Peergos (tripod0429/peergos-app) that lists its databases under
localstorage.sqlite.paths. While testing backup and restore, I found that the SQLite dumps Cloudron takes during a backup are never applied on restore. A restored app gets the copies of its live database files that the backup upload made while the app was running.What happens
From box master 21b1abd:
backupSqlitedumps each listed database withsqlite3 <db> .dumpbefore the upload starts services.js#L331-353. That part works as intended.- The upload then copies the whole data directory, including the live database files. The listed paths aren't excluded.
- On restore,
restoreSqlitereplays each dump like this services.js#L363-382:
There's nodocker run --rm ... <app image> sqlite3 <db> < <dump>-i, so Docker doesn't pass stdin to the container.sqlite3reads nothing and exits 0, and the restore carries on as if it worked.
Quick check
printf 'CREATE TABLE t(x); INSERT INTO t VALUES(42); SELECT x FROM t;\n' | docker run --rm cloudron/base:6.0.0 sqlite3 printf 'CREATE TABLE t(x); INSERT INTO t VALUES(42); SELECT x FROM t;\n' | docker run --rm -i cloudron/base:6.0.0 sqlite3On my Cloudron server (Docker 29.6.2), the first command prints nothing and exits 0. The second prints
42. Podman 5.8.7 behaves the same way.Adding
-ialone isn't enoughThe live database is already in the restored data, so every
CREATE TABLEin the dump fails andsqlite3exits 1. Cloudron's shell helper turns any non-zero exit into an error (shell.js#L58-84), so with only-iadded, every restore of an app withsqlite.pathswould fail. If that error were ignored instead, tables without a unique key would get duplicate rows:$ sqlite3 live.db "CREATE TABLE notes (body text); INSERT INTO notes VALUES ('one');" $ sqlite3 live.db .dump > dump.sql $ sqlite3 live.db < dump.sql; echo "exit $?" Parse error near line 3: table notes already exists exit 1 $ sqlite3 live.db "select count(*) from notes;" 2Why it matters
For most apps a live copy is close enough, which is probably why this hasn't come up. But:
- A database being written while it's copied can come back corrupted, which is what the dumps are there to prevent.
- In WAL mode, the database and its
-walfile are copied at different moments. - Apps that keep files next to their database can get rows pointing to files the upload had already passed.
Suggested fix
- In
restoreSqlite, pass-itodocker runand replay each dump into a new file instead of the restored copy. Once the replay succeeds, move the new file over the database and delete any-journal,-walor-shmfile left from the live copy. - Optionally, leave the listed paths out of the upload, since the dumps replace them. That also avoids uploading every database twice.
-
-
G girish has marked this topic as solved
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login