The blanket *.sql ignore rule (meant for database dumps) also excluded deploy/mysql/init.sql, so it was never committed. On a fresh clone the compose bind mount resolves to a missing file, MySQL skips schema initialization, and every database-backed page throws.