部署ManusAI时数据库连接失败,说白了就是后端服务已经跑起来了,但跟PostgreSQL或SQLite之间没搭上线。这事儿在配置错位、服务没准备好、或者权限隔离的场景里特别常见。别急,下面按步骤来排查,基本都能解决。

确认数据库服务状态与可访问性
先进Manus项目部署目录,敲一句docker-compose ps,看看postgres(也可能是db)这个容器的状态是不是Up。如果显示Exit或Restarting,那说明数据库容器压根没启动起来。
接着跑docker-compose logs postgres,重点翻翻日志里有没出现FATAL: password authentication failed或者database system is shut down这样的错误——前者告诉你密码对不上,后者说明初始化流程还没走完。
要是日志里蹦出initdb: error: could not change permissions of directory "/var/lib/postgresql/data",那问题就清楚了:宿主机挂载的data目录权限被root锁死了,postgres用户写不进去。解决方法是在宿主机上执行sudo chown -R 999:999 ./postgres-data(999是PostgreSQL最新镜像默认的UID)。
核对.env文件中的数据库连接参数
打开项目根目录下的.env文件,逐项检查这几个关键字段:
DATABASE_URL:格式必须是postgresql://user:password@postgres:5432/manusdb(本地Docker网络下)或者sqlite:///./data/app.db(SQLite模式)。如果误写成了localhost而不是postgres,容器内的DNS解析不到,连接必然超时。
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB:这三个值必须跟docker-compose.yml里postgres服务的environment区块完全一致,大小写、特殊字符一个都不能差。
另外,如果用的是SQLite模式,路径必须是容器内的路径,不是宿主机上的绝对路径。比如./data/app.db没问题,但写成/home/user/manus/data/app.db就会报“no such file”的错误。
检查Docker网络连通性
第一步:进到backend容器内部,执行docker exec -it manus-backend sh。
第二步:在容器里装个telnet(如果没预装的话)。Alpine用apk add --no-cache telnet,Ubuntu用apt-get update && apt-get install -y telnet。
第三步:测试一下postgres服务的端口是否可达:telnet postgres 5432。如果返回Connection refused,说明postgres容器没在监听,或者网络隔离了;如果卡住没反应,那基本上是Docker网络没打通。
第四步:telnet通了但应用还是连不上?那就再跑个nslookup postgres,确认DNS解析出来的IP是postgres容器的IP。如果解析失败,检查docker-compose.yml里services.backend.depends_on有没有包含postgres,以及healthcheck配置是否到位——Manus最新模板要求postgres健康检查通过后backend才启动,这是很常见的坑。
重置数据库初始化流程
方法一:强制重建数据库容器(会清空所有数据)。执行docker-compose down -v → 删除./postgres-data目录 → docker-compose up -d postgres → 等日志里出现database system is ready to accept connections → 再启动全部服务docker-compose up -d。
方法二:跳过初始化,复用已有数据库。把docker-compose.yml里postgres服务的volumes挂载从./postgres-data:/var/lib/postgresql/data改成只读挂载./postgres-data:/var/lib/postgresql/data:ro,这样initdb就不会重复执行产生冲突。
方法三:手动注入初始结构(适合迁移场景)。准备好init.sql文件,包含CREATE TABLE和INSERT语句;在docker-compose.yml的postgres服务下添加command: ["-c", "shared_preload_libraries='pg_stat_statements'"],再把init.sql通过volumes: ["./init.sql:/docker-entrypoint-initdb.d/init.sql"]挂载进去。
