【问题标题】:A PostgreSQL 12 docker container failing to restart on a particular architecturePostgreSQL 12 docker 容器无法在特定架构上重新启动
【发布时间】:2019-12-24 17:59:07
【问题描述】:

如果你有树莓派,这个问题很简单,很容易重现。我正在尝试从基本备份恢复在 docker 容器内运行的 postgresql 12 数据库,但阻止这种情况发生的问题仅仅是使用 PG 12 和 armv71 我无法重新启动删除数据目录的容器,如下所述。

我在两个不同的环境中通过 DockerHub 使用官方的postgresql docker container,一个是我的本地开发环境,它是一台运行 Ubuntu 18 LTS 的 PC,另一个是 Raspberry Pi armv71。

我需要的操作是删除正在运行的容器上/var/lib/postgresql/data的内容,然后重新启动容器,根据文档,这将强制运行docker-entrypoint.sh脚本,让我的恢复脚本火(它在我的 Ubuntu 机器上执行)。

所以在我的电脑上这个过程可以正常工作:

docker run --name website_db_1

这只是启动默认/vanilla postgresql docker 容器(我故意遗漏了密码)

然后,一旦启动并运行,强制容器运行 docker-entrypoint.sh 脚本,我这样做:

docker exec -it website_db_1 bash -c "rm /var/lib/postgresql/data/* -r"
docker container restart website_db_1

容器应该重新初始化,并且正如我所指出的,如果我要将适当的恢复脚本添加到 docker-entrpoint.sh 文件或 init 文件夹中,我确实可以让 wal 存档恢复正常工作(在我的Ubuntu PC)。

在 armv71 架构上,但在我的 Raspberry Pi 上,此完全相同的代码会导致容器日志中出现以下错误:

initdb: error: directory "/var/lib/postgresql/data" exists but is not empty
db_1                           | If you want to create a new database system, either remove or empty
db_1                           | the directory "/var/lib/postgresql/data" or run initdb
db_1                           | with an argument other than "/var/lib/postgresql/data".

是说目录不为空,但应该是我刚刚用上一行删除了,代码在Ubuntu上运行正常。同样在 Pi 上,我已经从容器内观察,以确认目录在重新启动之前确实是空的。怎么回事?

另一个有趣的事实是,上面的这个过程在使用postgres 11 的两种架构上都可以正常工作,我只是在更新到postgres 12 后遇到了困难。

知道为什么 PG 12 会导致 armv71 出现此问题吗?如果您有 pi,这很容易重现。

如果它很重要,以下是我正在使用的 postgresql 版本:

PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on arm-unknown-linux-gnueabihf, compiled by gcc (Debian 8.3.0-6)
PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit

【问题讨论】:

    标签: postgresql docker


    【解决方案1】:

    您描述的序列尝试在数据库仍在运行时删除 PostgreSQL 数据目录。这很可能只会使事情变得混乱;当docker stop 发出关闭数据库的信号时,它可能会将一些数据写入该目录,因此当它重新启动时,它实际上不会为空。

    这些数据库容器的典型用途是使用docker run -v 选项将一些存储装载到容器中,这样,如果您删除并重新创建容器,仍然存在持久状态。

    docker run \
      --name website_db_1 \
      --net website_net -p 5432:5432 \
      -v $PWD/postgres:/var/lib/postgresql/data \
      postgres:12
    

    所以当这些指令说删除数据库状态时,它们的意思是停止容器,并删除主机存储:

    docker stop website_db_1
    docker rm website_db_1
    rm -rf postgres
    mkdir postgres
    docker run \
      --name website_db_1 \
      --net website_net -p 5432:5432 \
      -v $PWD/postgres:/var/lib/postgresql/data \
      postgres:12
    

    (在日常使用中,您不需要使用docker exec 来管理或操作容器。这里的postgres 图像行为在首次启动时自动执行所有必需的初始化是非常典型的。如果您需要运行@ 987654328@ shell 你可以从主机或其他容器中完成。)

    【讨论】:

    • 感谢您的回答,我同意您的方法更明智/稳定/正确!这样做的方式。但是,我遇到了数据目录所有权的权限问题,这使我无法在数据目录上使用已安装的卷。当我使用 -v 创建卷时,我收到错误 FATAL: data directory "/var/lib/postgresql/data" has wrong ownership
    • 我确信这是有原因的,但使用命名卷“解决”了权限问题。因此,我能够创建一个辅助容器,该容器能够修改 db 容器的内容,包括删除数据目录并确实对配置文件进行操作以启用 wal 归档、恢复等。我很惊讶这是使用 docker 的正确方法,但它似乎确实符合模式。如果您希望使用命名卷而不是具有本地定义路径的卷,请随时更新您的答案。非常感谢
    • 如果您通过 -v 选项将卷添加到 docker,您必须确保容器用户(我假设它不是 root,因为默认情况下它是 postgres -> github.com/docker-library/postgres/blob/…)拥有目录。在这种情况下,uid 也应该与 dockerhost 上的 uid 999 匹配。
    猜你喜欢
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2020-10-05
    • 2020-01-21
    相关资源
    最近更新 更多