Windows 上 Docker 容器中的 Postgresql:如何将数据保存到本地 Windows 文件夹

use*_*098 5 postgresql docker windows-10

我正在尝试在 Windows 上的 docker 容器中运行 postgres。我还想将数据保存在 windows 文件夹中,所以我尝试了这个:

mkdir c:\pgdata

PS > docker run --name postgres -v c:\pgdata:/var/lib/postgresql/data -d postgres
d12af76bed7f8078babc0b6d35710dfc02b12d650904ed53ca95bb99984e9b36
Run Code Online (Sandbox Code Playgroud)

这似乎有效,但容器没有运行,日志讲述了一个不同的故事:

2019-07-24 23:19:20.861 UTC [77] FATAL:  data directory "/var/lib/postgresql/data" has wrong ownership
2019-07-24 23:19:20.861 UTC [77] HINT:  The server must be started by the user that owns the data directory.
child process exited with exit code 1
Run Code Online (Sandbox Code Playgroud)

如果我删除了 volume 选项,它会正常启动,但是我不会将我的数据库文件保存在我想要的位置。我在这里做错了什么?

atl*_*ine 5

你没有做错,只要看看完整的日志:

The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 20
selecting default shared_buffers ... 400kB
selecting default timezone ... Etc/UTC
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
2019-07-25 01:28:18.301 UTC [77] FATAL:  data directory "/var/lib/postgresql/data" has wrong ownership
2019-07-25 01:28:18.301 UTC [77] HINT:  The server must be started by the user that owns the data directory.
child process exited with exit code 1
initdb: removing contents of data directory "/var/lib/postgresql/data"
running bootstrap script ...
Run Code Online (Sandbox Code Playgroud)

从上面,您可以看到fixing permissions on existing directory /var/lib/postgresql/data ... okdocker-entrypoint.sh 中执行哪个将所有权从 root 更改为 postgres,但不幸的是,这仅适用于 linux 主机而不适用于 windows 主机。

那么,为什么不能在windows上工作,看这个讨论,主要是因为目前的实现是基于CIFS/Samba,这使得docker无法改进它。

所以,我猜如果你坚持使用绑定挂载,你就没有机会将数据持久化到 Windows。

但是,如果您不坚持,更接近的解决方案可能会使用命名卷,如下所示:

PS C:\> docker volume create my-vol
my-vol
PS C:\> docker run --name postgres -v my-vol:/var/lib/postgresql/data -d postgres
079d4b5b3f73bc0c4c586cdfee3fdefc8a27cdcd409e857de985bead254cd23f
PS C:\> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
079d4b5b3f73        postgres            "docker-entrypoint.s…"   5 seconds ago       Up 2 seconds        5432/tcp            postgres
PS C:\> docker volume inspect my-vol
[
    {
        "CreatedAt": "2019-07-25T01:43:01Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
Run Code Online (Sandbox Code Playgroud)

最后,数据将保留在 中/var/lib/docker/volumes/my-vol/_data,但限制是此文件夹不在 Windows 上,它在 hyper-v 机器上,因为您可能知道docker for windows使用 hyper-v 来模拟 linux 内核。

但它可能仍然满足您的要求,因为即使您删除当前容器,下次如果您使用相同的卷名(这里是my-vol)挂载,数据仍将在新容器中,命名卷不会被删除即使容器被删除,它也会在 hyper-v 虚拟机中持久存在。