Docker Compose启动Postgres后立即关闭,GRANT权限失效如何解决?
Postgres容器重启后GRANT权限丢失的解决方法
问题描述
使用Docker Compose启动Postgres镜像时,容器启动后立即关闭。重启容器后,init.sh中创建的用户、init.sql创建的test表及插入的数据都能保留,但给APP_DB_USER设置的GRANT权限被重置,导致该用户无法访问test表。
原因分析
- 脚本执行顺序问题:Postgres按文件名排序执行
docker-entrypoint-initdb.d下的初始化脚本,若init.sh先于init.sql执行,GRANT ALL PRIVILEGES ON ALL TABLES仅对执行时已存在的表生效,后续init.sql创建的test表不会被纳入授权范围。 - 初始化脚本仅执行一次:首次启动且数据卷为空时才会运行初始化脚本,后续容器重启不会重复执行脚本,未被授权的新表权限无法自动补全。
- 遗漏序列权限:
serial类型字段依赖序列生成ID,仅授权表权限会导致用户无法操作序列,进而无法插入数据。
解决方案
方案1:调整脚本逻辑,表创建后再授权
将表创建逻辑整合到init.sh中,确保在创建表和数据后执行授权,同时补上序列权限:
#!/bin/bash set -e echo "START INIT-DB"; psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL CREATE USER $APP_DB_USER WITH PASSWORD '$APP_DB_PWD'; GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $APP_DB_USER; -- 创建test表并插入数据 CREATE TABLE test ( id serial PRIMARY KEY, test_int INT NULL, test_contents varchar(50) NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NULL, deleted_at TIMESTAMP NULL ); INSERT INTO test (test_int, test_contents) VALUES (12, 'abc'), (34, 'def'); -- 为已创建的表和序列授权 GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO $APP_DB_USER; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO $APP_DB_USER; EOSQL
方案2:设置默认权限,新表自动继承权限
在init.sh中配置默认权限,让后续创建的所有表和序列自动授予APP_DB_USER权限,同时通过脚本命名保证执行顺序(如01_init.sh、02_init.sql):
修改后的init.sh:
#!/bin/bash set -e echo "START INIT-DB"; psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL CREATE USER $APP_DB_USER WITH PASSWORD '$APP_DB_PWD'; GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $APP_DB_USER; -- 设置public schema默认权限,新表/序列自动授权 ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO $APP_DB_USER; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO $APP_DB_USER; -- 对已存在的表和序列兜底授权 GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO $APP_DB_USER; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO $APP_DB_USER; EOSQL
init.sql保持原内容不变,重命名为02_init.sql,确保在01_init.sh之后执行。
方案3:手动补全权限(临时应急)
若已有数据不想重新初始化,可进入容器手动执行授权命令:
# 进入运行中的Postgres容器 docker exec -it <你的Postgres容器名> psql -U postgres # 执行授权(替换APP_DB_USER为实际用户名) GRANT ALL PRIVILEGES ON TABLE test TO APP_DB_USER; GRANT ALL PRIVILEGES ON SEQUENCE test_id_seq TO APP_DB_USER;
内容的提问来源于stack exchange,提问作者ParkSY
相关产品推荐
相关产品推荐

