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

问题描述 投票:0回答:6

我的 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
只获得了
data
文件夹它,即
./database/data
已创建,但它是空的。为什么?

备注:

更新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

postgresql docker docker-compose docker-volume
6个回答
511
投票

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

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

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

202
投票

您可以为所有 Postgres 数据创建一个通用的 volume

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"
    }
]


18
投票

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

当您执行撰写时,它本质上只是分解为各种 docker 客户端命令,然后将其传递给守护进程。那么

./database
是相对于 daemon 的,而不是客户端。

现在,docker 开发团队在这个问题上进行了一些反复讨论,但最重要的是它可能会产生一些意想不到的结果。

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


9
投票

postgres
图像的Dockerfile包含这一行

VOLUME /var/lib/postgresql/data

当基于此镜像启动容器时,如果没有其他任何东西挂载到那里,Docker 将创建一个匿名卷并自动挂载它。您可以使用

docker volume ls
等命令查看此卷,这也是您引用的
docker inspect
输出中的第二个挂载。

这样做的主要后果是您的外部卷安装必须位于

/var/lib/postgresql/data
而不是父目录。 (另请参阅@AlexLenail 的回答。)

如果您在

/var/lib/postgresql
上挂载主机目录,则:

  1. Docker 在内部对挂载进行排序,因此父目录首先挂载。
  2. 主机目录挂载在
    /var/lib/postgresql
  3. /var/lib/postgresql/data
    上未安装任何内容,因此 Docker 创建了匿名卷。
  4. 安装点不存在(它位于空的绑定安装主机目录中),因此 Docker 创建它,同时在主机上创建
    ./database/data
    目录。
  5. 匿名卷安装在该目录上,但仅在容器文件系统中。

结果就是您所看到的,数据库显然运行正常,但其数据不一定会持久化,您只能得到主机上空的

data
目录。


3
投票

我认为你只需要首先使用

docker create -v /location --name
在 docker 外部创建卷,然后重用它。

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


0
投票

我遇到了类似的问题,除了指定的卷之外,postgres 还会创建一个匿名卷。

  postgres:
    container_name: postgres
    image: postgres:15
    environment:
      PGUSER: postgres
      POSTGRES_PASSWORD: postgres
      PGDATA: /data/postgres
    volumes:
      - postgres_data:/data/postgres

事实证明,指定 PGDATA 环境变量会导致这种情况。容器将正确使用 postgres_data 卷,但还会创建一个空的匿名卷。

您可以使用

docker inspect postgres
找出已使用的卷,这是输出的
Mounts
部分:

    "Mounts": [
        {
            "Type": "volume",
            "Name": "modular-service-layer_postgres_data",
            "Source": "/var/lib/docker/volumes/modular-service-layer_postgres_data/_data",
            "Destination": "/data/postgres",
            "Driver": "local",
            "Mode": "z",
            "RW": true,
            "Propagation": ""
        },
        {
            "Type": "volume",
            "Name": "ceef11ea50a07400a798fbda75db4896f35a4a33d41c70cc68f976c187736dbd",
            "Source": "/var/lib/docker/volumes/ceef11ea50a07400a798fbda75db4896f35a4a33d41c70cc68f976c187736dbd/_data",
            "Destination": "/var/lib/postgresql/data",
            "Driver": "local",
            "Mode": "",
            "RW": true,
            "Propagation": ""
        }
    ],

我通过直接使用正确的安装点而不设置 PGDATA 修复了这个问题:

  postgres:
    container_name: postgres
    image: postgres:15
    environment:
      PGUSER: postgres
      POSTGRES_PASSWORD: postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data
© www.soinside.com 2019 - 2024. All rights reserved.