ChatGPT解决这个技术问题 Extra ChatGPT

如何使用卷将数据保存在 dockerized postgres 数据库中

我的 docker compose 文件有三个容器,web、nginx 和 postgres。 Postgres 看起来像这样:

postgres:
  container_name: postgres
  restart: always
  image: postgres:latest
  volumes:
    - ./database:/var/lib/postgresql
  ports:
    - 5432:5432

我的目标是将对应于 postgres 容器内名为 ./database 的本地文件夹的卷安装为 /var/lib/postgres。当我启动这些容器并将数据插入到 postgres 中时,我确认 /var/lib/postgres/data/base/ 已充满我正在添加的数据(在 postgres 容器中),但在我的本地系统中,./database 仅在它,即 ./database/data 已创建,但它是空的。为什么?

笔记:

这表明我的上述文件应该可以工作。

这个人正在使用有趣的 docker 服务

更新 1

根据尼克的建议,我做了一个 docker inspect 并发现:

    "Mounts": [
        {
            "Source": "/Users/alex/Documents/MyApp/database",
            "Destination": "/var/lib/postgresql",
            "Mode": "rw",
            "RW": true,
            "Propagation": "rprivate"
        },
        {
            "Name": "e5bf22471215db058127109053e72e0a423d97b05a2afb4824b411322efd2c35",
            "Source": "/var/lib/docker/volumes/e5bf22471215db058127109053e72e0a423d97b05a2afb4824b411322efd2c35/_data",
            "Destination": "/var/lib/postgresql/data",
            "Driver": "local",
            "Mode": "",
            "RW": true,
            "Propagation": ""
        }
    ],

这使得数据似乎被我自己没有编码的另一卷偷走了。不知道为什么会这样。 postgres 图像是否为我创建了该卷?如果是这样,有没有办法使用那个卷来代替我重新启动时安装的卷?否则,是否有禁用其他卷并使用我自己的卷的好方法,./database

更新 2

感谢尼克,我找到了解决方案! (和另一位朋友)在下面回答。

您是否已经运行 initdb 命令行来初始化您的数据库集群?
你确定你的数据子目录真的是空的吗?它可能具有特殊的访问权限。
谢谢你这么快回复我!我正在使用烧瓶应用程序,因此我在启动容器后从 docker runfrom app import dbdb.create_all()。我不直接从命令行initdb
@YaroslavStavnichiy 我不知道除了 sudo su - 并查看 ./database/data 之外的其他方法。据我所知,里面什么都没有。
有人可能会觉得这很有用:示例 compose 文件持久化 postgres、弹性搜索和媒体数据,stackoverflow.com/a/56475980/5180118

A
Alex Lenail

奇怪的是,解决方案最终变成了改变

volumes:
  - ./postgres-data:/var/lib/postgresql

volumes:
  - ./postgres-data:/var/lib/postgresql/data

这个答案的快速“为什么”(有效)。根据 postgres 人的说法,默认数据目录是 /var/lib/postgresql/data - 您可以在此处阅读 PGDATA 变量说明:store.docker.com/images/…
在上面的问题中,OP 说它在最后没有 /data 的情况下对他有用。那是对的吗?
并将本地目录添加到您的 .dockerignore 文件中,尤其是在您将其转换为生产映像时。有关讨论,请参见 codefresh.io/blog/not-ignore-dockerignore
这对我仍然不起作用(mac os x high sierra)
@OlliD-Metz 在它工作之前我必须做一个 docker rm my_postgres_container_1 (也是 High Sierra)。
C
Community

您可以为所有 Postgres 数据创建一个公共卷

 docker volume create pgdata

或者您可以将其设置为撰写文件

   version: "3"
   services:
     db:
       image: postgres
       environment:
         - POSTGRES_USER=postgres
         - POSTGRES_PASSWORD=postgress
         - POSTGRES_DB=postgres
       ports:
         - "5433:5432"
       volumes:
         - pgdata:/var/lib/postgresql/data
       networks:
         - suruse
   volumes: 
     pgdata:

它将创建卷名 pgdata 并将该卷挂载到容器的路径。

您可以检查此卷

docker volume inspect pgdata

// output will be
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
        "Name": "pgdata",
        "Options": {},
        "Scope": "local"
    }
]

评论有点晚,但如果我做docker-compose down -v,这不会清除数据。解决方案是什么?
@Sid,是的,会的!请小心使用此选项。
所以使用 docker-compose [down] 卷不再持续存在?是否完全清理卷?
@Sid 稍后发表评论,但您可以使用 docker-compose down --rmi all 没有 -v 选项,它会清除“所有内容”except卷,即容器、网络、图像等。我在部署时这样做,同时允许数据持久性。
suruse 有什么用?
N
Nick Burke

我会避免使用相对路径。请记住,docker 是一个守护进程/客户端关系。

当您执行 compose 时,它实际上只是分解为各种 docker 客户端命令,然后将其传递给守护进程。该 ./databasedaemon 相关,而不是客户端。

现在,the docker dev team has some back and forth on this issue,但最重要的是它可能会产生一些意想不到的结果。

总之,不要使用相对路径,使用绝对路径。


感谢您的回答!可悲的是,我认为它不起作用。我把行改成绝对路径,插入数据后,database/data文件夹还是空的=(
K. 接下来是在容器上运行 docker inspect 并确保容器知道卷(以防 compose 被混淆或其他情况)。 (注意: docker inspect 可能有敏感数据,所以不要在没有修改的情况下将其粘贴到这里 ;-) 之后,这是检查权限的问题(尽管这通常会显示错误)
啊哈! @Nick Burke 我想你找到了一些东西。我已经更新了这个问题。
l
leldo

我认为您只需要先使用 docker create -v /location --name 在 docker 外部创建卷,然后再重用它。

当我经常使用 docker 时,不可能使用带有 dockerfile 定义的静态 docker 卷,所以我的建议是尝试命令行(最终使用脚本)。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅