Docker PostgreSQL镜像NFS挂载权限问题:备份用户无法读取数据
PostgreSQL Docker NFS卷权限问题解决方案
问题概述
使用PostgreSQL(及Redis)Docker镜像时,通过NFS挂载Synology NAS存储卷,服务用户(UID 1050)运行数据库,但备份用户(UID 1051)无法读取数据目录文件——PostgreSQL会自动修改文件权限,导致备份用户无读取权限。当前Docker Compose配置如下:
services: postgresql: image: docker.io/library/postgres:12-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] start_period: 20s interval: 30s retries: 5 timeout: 5s user: "1050:100" volumes: - persist_postgresql:/var/lib/postgresql/data - nss:/etc/nss:ro environment: - POSTGRES_PASSWORD=xxx - POSTGRES_USER=xxx - POSTGRES_DB=xxx - NSS_WRAPPER_PASSWD=/etc/nss/passwd - NSS_WRAPPER_GROUP=/etc/nss/group networks: - default backup: image: restic/restic entrypoint: sh -c command: > "([ -f /srv/restic-repo/config ] || (restic init --repo /srv/restic-repo; mkdir /srv/restic-repo/tmp)) && restic backup --host myHost --exclude=\"sends\" --no-scan /source && restic forget --keep-hourly 168 --keep-daily 30 --keep-weekly 52 --keep-monthly 60" volumes: - persist_postgresql:/source - target:/srv/restic-repo environment: - RESTIC_REPOSITORY=/srv/restic-repo - RESTIC_PASSWORD=xxx - TMPDIR=/srv/restic-repo/tmp - RESTIC_CACHE_DIR=/srv/restic-repo/cache - RESTIC_COMPRESSION=max user: "1051:100" deploy: labels: - "swarm.cronjob.enable=true" - "swarm.cronjob.schedule=0 0 * * * *" - "swarm.cronjob.skip-running=true" restart_policy: condition: none volumes: persist_postgresql: driver_opts: type: "nfs" o: "addr=192.168.xxx,nolock,soft,rw" device: ":xxx/postgresql" nss: driver_opts: type: "nfs" o: "addr=192.168.1.172,nolock,soft,ro" device: ":xxx/nss"
解决方案
1. 共享组权限方案(最直接)
- 创建共享组:在NAS和Docker主机上创建GID一致的共享组(例如GID 1000),将UID 1050和UID 1051加入该组。
- 调整NFS挂载选项:修改
persist_postgresql卷的o参数,添加gid=1000,umask=002,确保新文件默认开放组读取权限:volumes: persist_postgresql: driver_opts: type: "nfs" o: "addr=192.168.xxx,nolock,soft,rw,gid=1000,umask=002" device: ":xxx/postgresql" - 设置数据目录权限:首次启动前,在NAS上手动调整数据目录权限,添加setgid位确保新文件继承组权限:
chown -R 1050:1000 /path/to/postgresql chmod -R g+rws /path/to/postgresql - 更新容器用户组:将PostgreSQL和备份服务的用户组改为共享组GID 1000:
services: postgresql: user: "1050:1000" backup: user: "1051:1000"
2. 自定义PostgreSQL Umask
PostgreSQL默认umask为077,会限制其他用户访问。可以通过以下方式修改:
- 修改容器启动脚本:创建自定义entrypoint脚本,设置umask后启动postgres:
#!/bin/sh umask 002 exec docker-entrypoint.sh "$@" - 挂载自定义entrypoint:在Compose中挂载该脚本到容器,覆盖默认entrypoint:
services: postgresql: entrypoint: /custom-entrypoint.sh volumes: - ./custom-entrypoint.sh:/custom-entrypoint.sh:ro
3. Synology NAS NFS权限配置
在NAS的NFS共享设置中,调整导出选项:
- 勾选「启用NFSv4.1」(可选,更稳定)
- 添加导出选项:
rw,sync,no_subtree_check,all_squash,anonuid=1050,anongid=1000 - 确保共享目录的权限设置为:所有者UID1050(读/写/执行),组GID1000(读/执行)
4. 数据库级备份(推荐)
避免直接备份数据目录,改用PostgreSQL原生备份工具:
- 修改备份服务,连接到PostgreSQL容器执行
pg_dump:services: backup: image: postgres:12-alpine command: > sh -c "pg_dump -h postgresql -U $${POSTGRES_USER} -d $${POSTGRES_DB} > /backup/db_dump.sql && restic backup /backup/db_dump.sql && restic forget --keep-hourly 168 --keep-daily 30 --keep-weekly 52 --keep-monthly 60" environment: - POSTGRES_USER=xxx - POSTGRES_PASSWORD=xxx - RESTIC_REPOSITORY=/srv/restic-repo - RESTIC_PASSWORD=xxx volumes: - target:/srv/restic-repo - ./backup:/backup user: "1051:1000"
这种方式无需处理文件系统权限,更安全可靠。
验证步骤
- 启动PostgreSQL容器后,检查数据目录权限:
确认文件组权限为docker exec postgresql ls -l /var/lib/postgresql/datar--或rw-。 - 测试备份用户读取权限:
docker exec backup su -u 1051 -c "cat /source/pg_hba.conf"
内容的提问来源于stack exchange,提问作者Atomium
相关产品推荐
相关产品推荐

