跳转到内容

PostgreSQL:给其他应用提供数据库

很多自托管应用需要一个数据库。这一页讲通用的部署和备份方式。

数据库不能靠直接复制文件来备份

在数据库运行期间直接复制数据目录,得到的副本很可能是不一致的,恢复时报错。必须用数据库自己的导出工具,或者在完全停止容器后再复制。

部署

yaml
services:
  db:
    image: postgres:16
    container_name: app-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: 用强密码替换
    volumes:
      - /vol1/docker/app/db:/var/lib/postgresql/data

要点:

  • 固定主版本号(这里是 16),不要用 latest。PostgreSQL 跨主版本升级需要执行数据迁移,镜像自动跳版本会导致容器起不来。
  • 不要映射端口到宿主机,除非确实需要从外部连接。同一个 compose 网络内的应用容器用服务名(这里是 db)就能访问。
  • 数据目录建议放在固态盘上,机械盘上的随机写入会让硬盘无法休眠。

备份

pg_dump 导出逻辑备份:

sh
docker exec app-db pg_dump -U appuser -d appdb > /vol1/backup/appdb-$(date +%F).sql

docker exec 在运行中的容器里执行命令;-U 指定用户;-d 指定数据库;输出重定向到一个带日期的文件。把这条命令做成每日定时任务,并设置失败通知。

恢复时,把 SQL 文件导入一个空数据库即可。恢复流程要实际演练过,见恢复演练

升级主版本

  1. pg_dump 导出完整备份。
  2. 停止并删除旧容器(保留数据目录)。
  3. 把数据目录移到别处存档,创建一个新的空目录。
  4. 用新版本镜像启动,导入备份。
  5. 验证应用能正常工作后,再考虑清理存档。

跳过第 1 步直接换镜像版本,容器会因数据目录版本不匹配而拒绝启动。

已知坑

  • 密码写在 compose 文件里,注意这个文件的权限,也不要提交到公开仓库。
  • 多个应用共用一个数据库实例可以省资源,但升级时会互相牵制,新手建议每个应用独立一个。
  • 数据库容器占用内存不低,规划时算进去。

参考资料

fnOS 非官方中文使用指南,与飞牛官方无隶属关系。