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

Docker Compose启动Postgres后立即关闭,GRANT权限失效如何解决?

Postgres容器重启后GRANT权限丢失的解决方法

问题描述

使用Docker Compose启动Postgres镜像时,容器启动后立即关闭。重启容器后,init.sh中创建的用户、init.sql创建的test表及插入的数据都能保留,但给APP_DB_USER设置的GRANT权限被重置,导致该用户无法访问test表。

原因分析

  1. 脚本执行顺序问题:Postgres按文件名排序执行docker-entrypoint-initdb.d下的初始化脚本,若init.sh先于init.sql执行,GRANT ALL PRIVILEGES ON ALL TABLES仅对执行时已存在的表生效,后续init.sql创建的test表不会被纳入授权范围。
  2. 初始化脚本仅执行一次:首次启动且数据卷为空时才会运行初始化脚本,后续容器重启不会重复执行脚本,未被授权的新表权限无法自动补全。
  3. 遗漏序列权限: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:57:10