MacOS(M2 Max)下docker-compose启动Postgres挂载权限异常
Apple M2 Max macOS下Docker Compose挂载Postgres初始化脚本权限问题解决
问题详情
在Apple M2 Max芯片的MacOS系统中,通过docker-compose启动Postgres 14服务时,挂载本地./db目录到容器内/docker-entrypoint-initdb.d/路径后,容器日志报错:
ls: reading directory '/docker-entrypoint-initdb.d/': Operation not permitted
相同配置在其他操作系统(如Linux、Intel芯片MacOS)可正常运行。
当前使用的配置文件及环境信息:
docker-compose.yml
version: '3.8' services: db: image: postgres:14 environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres volumes: - ./db:/docker-entrypoint-initdb.d ports: - 5432:5432
init.sh
#!/bin/bash set -e psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL CREATE USER docker; CREATE DATABASE docker; GRANT ALL PRIVILEGES ON DATABASE docker TO docker; EOSQL
Docker版本
Client: Cloud integration: v1.0.35 Version: 24.0.2 API version: 1.43 Go version: go1.20.4 Git commit: cb74dfc Built: Thu May 25 21:51:16 2023 OS/Arch: darwin/arm64 Context: desktop-linux Server: Docker Desktop 4.21.1 (114176) Engine: Version: 24.0.2 API version: 1.43 (minimum version 1.12) Go version: go1.20.4 Git commit: 659604f Built: Thu May 25 21:50:59 2023 OS/Arch: linux/arm64 Experimental: false containerd: Version: 1.6.21 GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8 runc: Version: 1.1.7 GitCommit: v1.1.7-0-g860f061 docker-init: Version: 0.19.0 GitCommit: de40ad0
问题原因
M系列芯片的MacOS对文件系统权限管控更严格,主要触发原因包括:
- Docker Desktop未获得当前项目目录的文件共享权限
- 本地挂载目录被MacOS系统完整性保护(SIP)限制访问
- 本地目录或脚本的权限不足,导致容器内postgres进程无法读取
解决方法
1. 检查并开启Docker文件共享权限
- 打开Docker Desktop,进入偏好设置 > Resources > File Sharing
- 确认当前项目所在的父目录(比如
/Users/你的用户名)已被添加到共享列表,勾选后点击Apply & Restart重启Docker
2. 调整本地目录及脚本权限
执行以下命令,确保挂载目录和脚本有足够的访问权限:
# 给db目录添加读权限 chmod -R 755 ./db # 确保目录归属当前用户 chown -R $(whoami):staff ./db # 给init.sh添加可执行权限 chmod +x ./db/init.sh
3. 避免挂载受SIP保护的目录
不要将项目放在/System、/Library等受SIP保护的系统目录下,建议迁移到/Users目录下的个人文件夹内。
4. 改用Docker命名卷挂载(替代方案)
如果本地目录挂载始终有问题,可以改用Docker命名卷来存储初始化脚本,避免权限冲突:
修改docker-compose.yml:
version: '3.8' services: db: image: postgres:14 environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres volumes: - db-init:/docker-entrypoint-initdb.d - postgres-data:/var/lib/postgresql/data ports: - 5432:5432 volumes: db-init: postgres-data:
然后将本地的init.sh复制到命名卷中:
docker run --rm -v $(pwd)/db:/source -v db-init:/target alpine cp /source/init.sh /target/
最后启动服务:
docker-compose up -d
内容的提问来源于stack exchange,提问作者sandwichie lim
相关产品推荐
相关产品推荐

