Postgres Docker镜像未使用自定义名称创建数据库。

28
postgres Docker镜像的文档关于环境变量POSTGRES_DB说道:

当镜像首次启动时,可以使用此可选环境变量来定义默认数据库的不同名称。如果未指定,则将使用POSTGRES_USER的值。

但是我发现这完全不正确。例如,使用以下配置:

version: '3.7'

services:
  db:
    image: postgres:11.3-alpine
    restart: always
    container_name: store
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=custom
      - POSTGRES_DB=customname
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password

volumes:
  postgres_data:

secrets:
  db_password:
    file: config/.secrets.db_password

默认数据库叫做postgres,而不是我指定的customname

$ docker exec -it store psql -U custom customname
psql: FATAL:  database customname does not exist
$ docker exec -it store psql -U custom postgres
psql (11.3)
Type help for help.

postgres=# ^D

我是否漏掉了一些显而易见的东西?

3个回答

36

像您做的那样提供环境变量,应该会在容器初始化时创建customname数据库。没有必要在/docker-entrypoint-initdb.d/脚本中创建用户名和数据库。

我建议确保没有挂起的postgres_data卷。如果之前启动过容器而没有指定环境变量,则会为默认的postgres数据库创建卷。下次您使用指定了POSTGRES_DB环境变量来启动容器时,将跳过数据库创建部分。

为了确保,请删除任何已创建的卷(名称应该类似于*_postgres_data)。

docker volume ls
docker volume rm <volume_name>

同样,请参阅用户和数据库未从环境变量参数创建。希望这能有所帮助。


1
哇,你做得太好了!我搜索了很多次,但是我没有找到那个问题。最终一切都清楚了。 - rubik
当我运行 docker volume ls 命令时,它会给我返回一个很长的卷列表,所有这些卷都由类似哈希值的东西描述,我没有看到任何 postgres_data。这是格式改变了还是意味着我没有这样的卷? - cgold
@cgold postgres_data 是在相关的 docker_compose 文件中声明的卷的名称。在您的情况下,由 ls 命令返回的哈希值卷名称是匿名卷。PostgreSQL 的 Dockerfile 定义了一个用于存储数据库数据的 /var/lib/postgresql/data 卷。如果该卷没有显式地映射到主机上,则会创建一个匿名卷。使用 docker inspect -f '{{ .Mounts }}' container-id 命令可以查看映射。 - b0gusb
docker volume ls 对我来说返回了一个空列表。我在重新启动容器之前删除了主机卷,但它仍然创建了默认数据库而不是自定义数据库。 - Kashif Nazar

2
你需要首先创建数据库。
如果你想要自动为新的数据目录创建数据库,那么官方的 Docker Postgres 镜像有一个选项可以通过在 /docker-entrypoint-initdb.d/ 目录中放置扩展名为 .sql初始化脚本 来实现。
例如,创建一个包含以下内容的文件:
CREATE USER custom_user;
CREATE DATABASE custom_db;
GRANT ALL PRIVILEGES ON DATABASE custom_db TO custom_user;

将其保存到容器中的/docker-entrypoint-initdb.d/create-db.sql,例如在Dockerfile中使用COPY。该目录中扩展名为.sql的脚本仅在DATA目录为空时运行,并且多个文件将按文件名的字母顺序运行。
如果您想手动设置它,也可以使用createdb实用程序
createdb [connection-option...] [option...] [dbname [description]]

或者通过连接到postgres数据库并使用CREATE DATABASE ...命令来创建数据库,例如:
docker exec -it store psql -U postgres -c 'CREATE DATABASE customname;'

如果您像问题中所述那样进行交互连接,您可以执行以下操作:

最初的回答:

$ docker exec -it store psql -U postgres
psql (11.3)
Type help for help.

postgres=# CREATE DATABASE customname;
CREATE DATABASE

postgres=# \c customname

最后一个命令将连接您到名为customname的数据库。

文档的措辞让我认为数据库会自动创建。但我需要在组合管道期间创建它的方法。 - rubik
实际上,我再次阅读了文档,它说“当图像第一次启动时创建的数据库”。因此,它肯定似乎应该自动创建。 - rubik
你之前在那个卷上创建了一个集群,然后才将该环境变量添加到docker-compose中吗?如果集群已经存在,我认为它不会创建一个新的数据库。 - Jeremy
@rubik - 好的,我现在更明白你想做什么了。我更新了答案。 - isapir

1
如果您在第一次运行后更改了用户名/密码,请尝试删除先前创建的卷。
    docker volume rm <volume-name>

然后再次运行组合文件。

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