如何使用卷将数据持久化在dockerized postgres数据库中


204

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

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

我的目标是安装一个./database与postgres容器内称为的本地文件夹相对应的卷/var/lib/postgres。当我启动这些容器并将数据插入postgres时,我验证了/var/lib/postgres/data/base/所添加数据的全部内容(在postgres容器中),但是在我的本地系统中,./databasedata在其中获得了一个文件夹,即已./database/data创建,但它为空。为什么?

笔记:

更新1

根据Nick的建议,我做了一个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命令行来初始化数据库集群了吗?
塞巴斯蒂安·韦伯

您确定数据子目录确实为空吗?它可能具有特殊的访问权限。
Yaroslav Stavnichiy

感谢您如此迅速地回复我!我用的烧瓶中的应用程序,所以我from app import dbdb.create_all()docker run开始的容器后。我不是initdb直接从命令行输入。
Alex Lenail17年

1
@YaroslavStavnichiy我不知道该如何检查sudo su -并查看./database/data。据我所知,那里什么也没有。
Alex Lenail17年

有人可能会觉得这很有用:样本撰写文件可持久保存postgres,弹性搜索和媒体数据,stackoverflow.com
a/56475980/5180118

Answers:


251

奇怪的是,解决方案最终不得不改变

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

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

45
只是此问题的快速“为什么”(有效)。每Postgres的乡亲,默认数据目录是/var/lib/postgresql/data-你可以在这里阅读PGD​​ATA变量说明:store.docker.com/images/...
马特Pavelle

2
在上面的问题中,OP表示在没有/ data的情况下对他有用。那是对的吗?
2017年

2
并将本地目录添加到您的.dockerignore文件中,特别是如果您将其截断成生产映像时尤其如此。有关讨论,请参见codefresh.io/blog/not-ignore-dockerignore
dsz

4
这仍然对我不起作用(mac os x high sierra)
olidem

1
@ OlliD-Metz我必须先做一个,docker rm my_postgres_container_1然后才能工作(也是High Sierra)。
丰富的

100

您可以为所有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"
    }
]

8
评论有点晚,但是如果执行,就不会清除这些数据docker-compose down -v。对此有什么解决方案?
2017年

3
@Sid,是的,它将!请谨慎使用此选项。
olidem '18

1
因此,使用docker-compose [down]不再保留该卷?是否完全清除了卷?
保罗

2
@Sid Commenting甚至更晚,但是您可以docker-compose down --rmi all 使用该-v选项而使用,它会清除“所有内容”,但不包括卷,即容器,网络,图像等。我在部署时会这样做,同时允许数据持久化。
–'code_dredd

13

我会避免使用相对路径。请记住,泊坞窗是守护程序/客户端关系。

在执行撰写时,它实际上只是分解为各种Docker客户端命令,然后将其传递给守护程序。那./database是相对于守护程序,而不是客户端。

现在,docker开发团队在此问题上来回走了一些,但最重要的是,它可能会产生一些意想不到的结果。

简而言之,不要使用相对路径,而要使用绝对路径。


感谢您的回答!可悲的是,我认为它没有用。我将行更改为绝对路径,并在插入数据后,database/data文件夹仍然为空=(
Alex Lenail

K.下一步是docker inspect在容器上运行,并确保容器知道其体积(以防compose混淆或其他原因)。(注意:docker inspect可能具有敏感数据,因此请不要在不作任何改动的情况下将其粘贴到此处;-)之后,这是检查权限的问题(尽管通常会显示错误)
Nick Burke

啊哈!@尼克·伯克(Nick Burke)我想您已经找到了一些东西。我已经更新了问题。
Alex Lenail17年

2

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.