使用Docker Compose运行PostgreSQL时出现“FATAL: role"root"不存在”的错误。

98

我正在尝试在本地 Windows 机器上使用 Docker Desktop 创建一个简单的演示,使用的是 PostgreSQL 数据库。
这是我的 YAML Docker Compose 文件,名为 img.yaml

version: '3.6'

services:

    postgres-demo:
      image: postgres:11.5-alpine
      container_name: postgres-demo
      environment:
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=Welcome
        - POSTGRES_DB=conference_app
      healthcheck:
        test: ["CMD-SHELL", "pg_isready -U postgres"]
        interval: 10s
        timeout: 5s
        retries: 5
      ports:
        - 5432:5432
      volumes:
        - .:/var/lib/my_data
      restart: always

我正在使用以下命令运行它: docker-compose -f img.yaml up 并获得以下输出:

Starting postgres-demo ... done
Attaching to postgres-demo
postgres-demo    | 2020-02-12 17:07:46.487 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres-demo    | 2020-02-12 17:07:46.487 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres-demo    | 2020-02-12 17:07:46.508 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-demo    | 2020-02-12 17:07:46.543 UTC [18] LOG:  database system was shut down at 2020-02-12 17:07:10 UTC
postgres-demo    | 2020-02-12 17:07:46.556 UTC [1] LOG:  database system is ready to accept connections

然后,使用以下命令在容器中打开bash:docker exec -it d47056217a97 bash
我想观看容器中的数据库,因此在bash中运行以下命令:psql \dt
但是出现了错误:psql: FATAL: role "root" does not exist.
尝试使用以下命令创建数据库:psql> create database conference_app;时出现错误:psql: FATAL: role "conference_app" does not exist.
我感到困惑。我做错了什么?我的yaml文件有问题吗?

7个回答

118
如果您没有指定PGUSER环境变量,那么psql将假定您想要使用当前的操作系统用户作为数据库用户名。在这种情况下,您正在使用root作为您的操作系统用户,并尝试以root登录,但是该用户在数据库中不存在。
您需要调用psql -U postgres或先调用su - Postgres 另请参阅postgresql文档 更新:有人建议将PGUSER更改为POSTGRES_USER - 这实际上是不正确的。Postgres会在环境中查找PGUSER,但如果您使用Docker,则可以通过使用POSTGRES_USER来告诉Docker正确的用户,该用户将被分配给PGUSER - 请参见入口源代码

1
我成功地完成了这个任务,不是通过image bash,而是使用命令:docker exec -it postgres-demo psql -U postgres -d conference_app -f /var/lib/my_data/insert_data.sql。 - Yaron
@Yaron 很好!同样的想法 :) - richyen
5
我是这样使用的: `环境: PGUSER: postgres`对我来说它很有效。 - thiagoBarbosa48

36

在docker-compose文件中,我为服务指定了user: postgres。然后删除了现有容器,以便在下一个docker-compose up执行中重启它。容器以用户"postgres"启动,因此您只需要从那里开始使用psql -l(不需要-U标志)

这是我的docker-compose文件

version: '3.1'
services:
  db:
    image: postgres:12.6-alpine
    restart: always
    container_name: postgres12_6
    user: postgres
    environment:
      - "POSTGRES_PASSWORD=postgres"
      - "ES_JAVA_OPTS=-Xms1024m -Xmx3072m"
    networks:
      - esnet
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

networks:
  esnet:

这个解决方案似乎是最容易理解的。谢谢! - Ananta K Roy

17

由于您在docker exec命令中未指定用户和数据库名称,因此容器假设您正在尝试使用root用户(当前用户)连接到db。

以下操作应有效:

docker exec -it <container_id/container_name> psql -U <user_name> <database_name>
docker exec -it d47056217a97 psql -U postgres conference_app

10
如果您还指定了除默认数据库之外的其他数据库,您还应该在pg_ready命令中包含此信息。
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d db-name -U db-user"]

在上面的代码片段中,我的数据库名称是db-name,并且使用了一个用户db-user。 尽管设置了POSTGRES_DBPOSTGRES_USER环境变量,但我还需要明确指定这一点。

4
如 richyen 在 answers 中所述,即使您已经设置了 POSTGRES_USER 变量,作为 richyen,您仍然需要设置 PGUSER 环境变量。这是因为 psqlpg_isready 是两个不同(尽管相关)的程序,它们具有不同的环境查找逻辑(一个查找 POSTGRES_USER,另一个查找 PGUSER)。
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: me
      PGUSER: me
    healthcheck:
      test: pg_isready

如果你只想依赖一个变量,并且不想用你的数据库用户名来“填补漏洞”,你可以直接将POSTGRES_USER的值放入健康检查的test命令中。
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: me
    healthcheck:
      test: pg_isready -U $$POSTGRES_USER

请注意,$$POSTGRES_USER 前面有两个美元符号,这是有意为之的。
之后,您可能还想根据 Christopher Peisert 的 answer 添加 -d db 选项。

3

docker-compose v2+更新

错误1 - 致命错误:角色"root"不存在

richyen的回答所述,请设置PGUSER环境变量。

注意:POSTGRES_USER本身不起作用。

错误2 - 致命错误:数据库"X"不存在

在这种情况下,X通常是PGUSER环境变量的值。

在设置PGUSER环境变量后,修复了原始错误,但引入了一个新错误:

致命错误:数据库"X"不存在

解决方案

修复方法是将数据库主机定义为其自己的Docker网络IP地址,如下所示:

services:
  server:
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:latest
    healthcheck:
      test: "pg_isready -h db"
      interval: 3s
      timeout: 5s
      retries: 5

这里的-h db是指db服务自己的Docker IP地址。通过这个配置,通常不需要传递额外的标志给pg_isready

对于任何想知道在哪里设置这个环境变量的人来说,即使我已经设置了POSTGRES_USER,我还需要在我的docker-compose.yml文件中为postgres容器设置PGUSER - undefined

1

在我的情况下,我使用的是Windows 10,尽管尝试了所有可能的方法,但仍然无法正常工作。

最终,我移除了所有相关的Docker镜像、Docker容器和本地主机文件夹,并重新启动了Windows。

这样一来,一切都恢复正常了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接