【问题标题】:Connecting Docker Postgres container to an existing empty database将 Docker Postgres 容器连接到现有的空数据库
【发布时间】:2020-04-10 04:58:47
【问题描述】:

我想创建一个 tarball,其中包含一个空数据库(即一系列空表)和一个启动 Postgres 容器的 shell 脚本,该容器将连接到空数据库。最终产品是一个 .tar.gz,其中包含一个数据库副本、一个启动脚本和一个停止脚本。这一切都是为了在 macOS 中工作

为了创建数据库,我在笔记本电脑上本地启动了一个 Postgres 服务器,并创建了一个名为“postgres-15year”的数据库。在 CLI 中使用“DBeaver”数据库管理器和“psql”,我可以看到 dbase 已正确创建且正常运行。

然后我创建了以下脚本:

start.sh

#!/bin/bash
echo $(pwd)
docker run --rm --name payments-15years -e POSTGRES_PASSWORD=docker -d -p5432:5432 -v$(pwd)/postgres-15year/data:/var/lib/postgresql/data:delegated postgres:11.6

stop.sh

#!/bin/bash
docker stop payments-15years
echo "docker stop payments-15years"

然后我将所有这些都放在一个我想要压缩包的目录中。

因此,用户将接收到压缩包,解压缩并运行启动脚本,并能够连接到具有预定义结构和模式的数据库。这是我认为“我的 start.sh”脚本正在做的事情:

  1. 创建容器名称“payments-15years”
  2. 为通用用户('postgres')设置数据库密码
  3. 将数据库端口设置为 5432 并将其映射到本地服务器端口 5432(不确定是否有必要,但所有示例似乎都可以 它)
  4. 将 db 映射到容器的 var/lib 和“委托”而不是 到“缓存”以便更改持续存在
  5. 将 Postgres docker 映像指定为 11.6

我的挑战是在运行启动脚本 'docker ps' 后返回:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
14d2cba6abe2        postgres:11.6       "docker-entrypoint.s…"   44 seconds ago      Up 42 seconds       0.0.0.0:5432->5432/tcp   payments-15years

但是当我这样做然后从 CLI 运行“psql”时:

docker exec -it payments-15years psql -U postgres

数据库('postgres-15year')未列出。

有人看出我的方法有什么问题吗?

注意:

  1. 我没有提供数据库,但它是带有架构的空表 已定义,以上所有脚本和图片应该足够了 重现问题。
  2. 我找到的最接近堆栈答案是 here,但它没有帮助。

【问题讨论】:

    标签: postgresql docker


    【解决方案1】:

    实际上当你用-v $(pwd)/postgres-15year/data:/var/lib/postgresql/data:delegated运行命令时,根据postgres-docker的官方文档。

    该命令的-v /my/own/datadir:/var/lib/postgresql/data 部分将底层主机系统中的/my/own/datadir 目录作为/var/lib/postgresql/data 挂载到容器内,PostgreSQL 默认将写入其数据文件。

    所以你只是在创建一个数据目录而不是数据库。您可以使用inspect关键字查看。

    docker container inspect <container_name>
    

    在您的方案中,payments-15years 提供了详细信息,

    "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/Users/macair/postgres-15year/data",
                    "Destination": "/var/lib/postgresql/data",
                    "Mode": "delegated",
                    "RW": true,
                    "Propagation": "rprivate"
                }
            ],
    

    要创建数据库,请像以前一样执行交互式会话并手动创建数据库或试试这个。

    docker run -it --rm --network some-network postgres psql -h some-postgres -U postgres
    

    【讨论】:

    • 我能够使用交互式创建数据库。为了用正确的模式填充空数据库,我有一个 pg-dump 文件 (.sql)。我不确定如何使该文件可用于容器。想法?
    • 你可以试试这样,在容器docker exec -it payments-15years psql -d your_db -a -f your_sql.sql运行本地模式
    • 是的,这有效:docker container exec -i payments-15years psql postgres_15year &lt; pcan_blank.sql -U postgres 基于此链接:nickjanetakis.com/blog/…
    • 对不起,我忘记了逗号中的&lt;。
    【解决方案2】:

    首先参考您的评论,

    我能够使用交互式创建数据库。为了用正确的模式填充空数据库,我有一个 pg-dump 文件 (.sql)。我不确定如何使该文件可用于容器。想法?

    如果你有转储文件,为什么要在容器启动后运行命令?

    最好让它成为 Dockerfile 的一部分,你不需要手动转储,Docker 镜像会处理它。

    FROM postgres
    ADD mydb.sql /docker-entrypoint-initdb.d
    

    现在,如果您启动容器,数据库将自动填充。

    初始化脚本

    如果您想在派生的图像中进行额外的初始化 从此,在下面添加一个或多个 *.sql、*.sql.gz 或 *.sh 脚本 /docker-entrypoint-initdb.d(必要时创建目录)。 入口点调用 initdb 后创建默认 postgres 用户 和数据库,它将运行任何 *.sql 文件,运行任何可执行的 *.sh 脚本,并获取其中找到的任何不可执行的 *.sh 脚本 目录在启动服务之前做进一步的初始化。

    postgress init DB

    现在来回答你的问题,你可以用 Tarball 做到这一点,tar 不处理体积,而 Postgres docker 图像带有 volume。所以你需要在启动时按照 Dockerfile 导入数据。

    【讨论】:

    • 好建议,但由于 tarball 的用户将在本地运行,因此不需要。我还添加了“备份”和“恢复”脚本,以便关闭容器将创建一个转储文件,而“恢复”将在启动时恢复数据库。这样,用户将拥有持久的数据库更改。
    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 2022-11-20
    • 2016-04-02
    • 1970-01-01
    • 2020-05-30
    相关资源
    最近更新 更多