You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器中PostgreSQL报postmaster.pid写入失败问题求助

PostgreSQL容器报"No space left on device"的排查与根治

核心成因分析

你遇到的情况很典型,看似磁盘容量足够但报空间不足,扩容后又突然多出大量空间,大概率是以下几种情况:

  • inode耗尽:df -h只看磁盘容量,df -i才看inode数量。如果有大量小文件(比如PostgreSQL WAL日志、Docker缓存文件),会把inode占满,此时磁盘容量还剩很多但无法新建文件(包括postmaster.pid锁文件)。
  • PostgreSQL WAL日志爆仓:如果归档配置异常(archive_command执行失败、归档存储不可用),PostgreSQL会一直保留WAL日志不删除,短时间内就能占满磁盘。扩容后归档恢复正常,旧WAL被自动清理,空间就释放了。
  • Docker容器日志无限制增长:PostgreSQL的日志默认输出到容器stdout/stderr,如果没配置日志轮转,大量日志会瞬间占满磁盘。扩容后日志驱动触发轮转,旧日志被删除,空间恢复。
  • 临时文件突发占用:大查询产生的临时表、排序临时文件,会临时占用大量磁盘空间,会话结束后自动清理。扩容后这些临时文件刚好被清理,所以空间剩余变多。

具体排查步骤

  • 先查inode使用率:执行df -i,看是否有文件系统的IUsed%达到100%。
  • 检查PostgreSQL WAL状态:
    1. 进入容器:docker exec -it <你的postgres容器ID> bash
    2. 查看WAL目录:psql -U <用户名> -c "show wal_dir"
    3. 统计WAL文件数量:ls -l <wal_dir路径> | wc -l,正常应该只有几十个到上百个,若有几千个就是归档失败。
    4. 检查归档配置:psql -U <用户名> -c "show archive_mode; show archive_command;",确保archive_mode=on且archive_command能正常执行(比如测试手动执行归档命令)。
  • 检查Docker容器日志大小:
    1. 查看日志文件路径:docker inspect <容器ID> | grep LogPath
    2. 统计日志大小:du -sh <日志文件路径>,如果几个G甚至几十G就是日志没限制。
  • 清理Docker无用资源:执行docker system df查看镜像、卷、缓存占用,用docker system prune -a清理未使用的镜像、容器、卷(注意先备份重要数据)。
  • 检查PostgreSQL数据目录各部分占用:进入容器后执行du -sh /var/lib/postgresql/data/*,看哪个子目录占空间最大。

根治方法

  • 配置PostgreSQL WAL自动清理:
    • 确保archive_mode=on,archive_command配置正确且归档存储可用(比如备份到对象存储、NFS)。
    • 设置合理的wal_keep_size(比如10GB),避免保留过多旧WAL。
    • 开启autovacuum(默认开启),定期清理旧数据和死元组。
  • 限制Docker容器日志大小:
    • 在docker-compose.yml中添加日志配置:
      services:
        postgres:
          logging:
            driver: json-file
            options:
              max-size: "100m"
              max-file: "5"
      
    • 或者用docker run命令添加参数:--log-driver json-file --log-opt max-size=100m --log-opt max-file=5
  • 监控磁盘和inode使用率:添加监控工具(比如Prometheus+Grafana),设置磁盘使用率≥80%、inode使用率≥90%的告警。
  • 定期清理Docker资源:每周执行docker system prune -f,清理无用的镜像、容器、卷和缓存。
  • 限制PostgreSQL临时文件:在postgresql.conf中设置temp_file_limit=10GB,避免单个会话的临时文件占满磁盘。

关于扩容后剩余空间达95%的解释

扩容后空间突然变多,是因为触发问题的临时占用(WAL日志、临时文件、容器日志)在扩容后被自动清理了:

  • 如果是WAL爆仓,扩容后归档进程恢复正常,旧WAL被归档后删除。
  • 如果是临时文件,产生临时文件的查询会话结束后,PostgreSQL自动清理了临时文件。
  • 如果是容器日志,扩容后日志驱动触发了轮转策略,删除了旧的大日志文件。

内容的提问来源于stack exchange,提问作者Rui Alves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 09:36:09