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

Docker Swarm集群中Postgres:10周期性Shutdown但仍存活问题

问题分析

从你的日志和配置来看,postgres出现周期性关闭恢复的核心原因是健康检查脚本在Docker Swarm环境下无法正常连接数据库,导致Swarm判定容器不健康并重启它。因为你挂载了持久化数据卷,容器重启时不需要重新初始化,直接启动postgres,所以表现为数据库进程周期性关闭后恢复。

具体来说,健康检查脚本中使用hostname -i获取容器IP的方式在Swarm的overlay网络环境下存在问题:

  • hostname -i可能返回多个IP地址(比如容器的overlay网络IP和本地回环IP),导致psql的--host参数错误,连接失败
  • 即使返回单个IP,Swarm环境下容器的IP可能会动态变化,依赖这个IP进行健康检查不可靠
解决方案

1. 修复健康检查脚本,改用Unix Socket连接

Unix Socket是postgres默认的连接方式,比TCP连接更可靠,且不受IP地址变化影响。修改你的健康检查脚本如下:

#!/bin/bash
set -eo pipefail
user="${POSTGRES_USER:-postgres}"
db="${POSTGRES_DB:-$POSTGRES_USER}"
export PGPASSWORD="${POSTGRES_PASSWORD:-}"
args=(
 --username "$user"
 --dbname "$db"
 --quiet
 --no-align
 --tuples-only
)
if select="$(echo 'SELECT 1' | psql "${args[@]}")" && [ "$select" = '1' ]; then
 exit 0
fi
exit 1

去掉--host参数后,psql会自动使用Unix Socket(/var/run/postgresql/.s.PGSQL.5432)连接,避免了IP相关的问题。

2. 移除Swarm不支持的container_name配置

在Docker Swarm模式下,container_name选项会被忽略,且可能限制服务的调度能力(比如无法运行多个副本)。从你的docker-compose.yml中删除这一行:

container_name: db_jackrabbit

3. 验证健康检查配置

确保健康检查的参数合理:

HEALTHCHECK --interval=30s --timeout=30s --retries=3 \
 CMD healthcheck

当前的配置是每30秒检查一次,超时30秒,重试3次后标记为不健康,这个配置是合理的,不需要调整。

4. 检查Swarm服务的重启策略

Swarm服务默认的重启策略是any(无论容器退出原因都会重启),如果希望避免健康检查失败后的频繁重启,可以调整为on-failure策略:

db_jackrabbit:
  # ... 其他配置
  deploy:
    restart_policy:
      condition: on-failure
      max_attempts: 5

这样只有当容器异常退出时才会重启,避免健康检查误判导致的频繁重启。

验证修复

修改后重新部署服务:

docker stack deploy -c docker-compose.yml <your-stack-name>

然后查看容器日志,确认postgres不再出现周期性的database system is shut down提示,且健康检查状态为healthy:

docker service logs <your-service-name>
docker service inspect --format '{{.Status.TaskStatus.State}}' <your-service-name>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:28:17