docker 容器中 PostgreSQL 的权限问题

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

我正在尝试使用 PostgreSQL 运行一个 docker 镜像,该镜像的卷配置为持久化数据。

docker-compose.yml

version: '3.1'

services:
  db:
    image: postgres
    restart: always
    volumes:
      - ./data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example

当我启动容器时,我会看到输出

修复现有目录 /var/lib/postgresql/data 的权限 ... ok

数据文件夹对我来说不再可读。

如果我提升自己并访问数据目录,我可以看到文件在那里。此外,命令

ls -ld data
给了我

drwx------ 19 systemd-coredump root 4096 May 17 16:22 data

我可以使用

sudo chmod 755 data
手动设置目录权限,但这只能在我重新启动容器之前有效。

为什么会发生这种情况,我该如何解决?

postgresql docker ubuntu docker-compose file-permissions
5个回答
17
投票

另一个答案确实指出了问题的根本原因,但是它指向的帮助页面不包含解决方案。这是我想出的让这个工作对我有用的东西:

  1. 使用普通的 docker-compose 文件启动容器,这将创建具有硬编码 uid:gid (999:999) 的目录
version: '3.7'

services:
  db:
    image: postgres
    container_name: postgres
    volumes:
      - ./data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: fake_database_user
      POSTGRES_PASSWORD: fake_database_PASSWORD
  1. 停止容器并手动将所有权更改为您想要的 uid:gid(我将在本示例中使用 1000:1000
$ docker stop postgres
$ sudo chown -R 1000:1000 ./data 
  1. 编辑你的 docker 文件以添加你想要的 uid:gid 并使用 docker-compose 再次启动它(注意
    user:
version: '3.7'

services:
  db:
    image: postgres
    container_name: postgres
    volumes:
      - ./data:/var/lib/postgresql/data
    user: 1000:1000
    environment:
      POSTGRES_USER: fake_database_user
      POSTGRES_PASSWORD: fake_database_password

您不能从一开始就使用

user:
的原因是,如果图像以不同的用户身份运行,则无法创建数据文件。

On the image documentation page, it does mention a solution to add a volume to expose the

/etc/passwd
file as read-only in the image when providing
--user
option, 然而,这对我来说不起作用最新的图像,因为我收到以下错误。事实上,三个建议的解决方案都不适合我。

initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted

6
投票

这是因为postgres镜像的dockerfile里面写的是什么
从第 15 行到第 18 行,您将看到使用了组 999 和用户 999。我猜在您的主机中,它们分别映射到

systemd-coredump
root
.

你需要知道,每当你在图像中使用用户/组时,如果 uid/gid 存在于你的主机中,那么它将被映射到它。

您可以从 postgres 图像 here 阅读 docker hub 上的文档。有一个部分 Arbitrary --user Notes 解释了它如何在此图像的上下文中工作。


1
投票

一个更简单和永久的解决方案如下:

将这些行添加到

~/.bashrc

export UID=$(id -u)
export GID=$(id -g)

重新加载你的外壳:

$ source ~/.bashrc

修改你的

docker-compose.yml
如下:

version: "3.7"
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    user: "${UID}:${GID}"
    ...

来源


1
投票

这是我所做的:


services:
    postgres:
        image: postgres:15.1
        restart: always
        environment:
            - POSTGRES_USER=my_user
            - POSTGRES_PASSWORD=my_user
            - POSTGRES_DB=my_user
        user: root
        ports:
            - "5432:5432"
        volumes:
            - /home/my_user/volumes/postgres/data:/var/lib/postgresql/data
            - /home/my_user/volumes/postgres/config:/etc/postgresql
    postgres_setup:
        image: postgres:15.1
        user: root
        volumes:
            - /home/my_user/volumes/postgres/data:/var/lib/postgresql/data
            - /home/my_user/volumes/postgres/config:/etc/postgresql
        entrypoint: [ "bash", "-c", "chmod 750 -R /var/lib/postgresql/data && chmod 750 -R /etc/postgresql"] 
        depends_on:
            - postgres
    pgadmin4:
        image: dpage/pgadmin4
        restart: always
        environment:
            - [email protected]
            - PGADMIN_DEFAULT_PASSWORD=my_user
            - PGADMIN_LISTEN_ADDRESS=0.0.0.0
        user: root
        ports:
            - "5050:80"
        volumes:
            - /home/my_user/volumes/pgadmin/data:/var/lib/pgadmin
        depends_on:
            - postgres_setup

postgres_setup 容器只是更改权限然后关闭


0
投票

我一直在为类似的问题而苦苦挣扎,当我试图解决 postgres(每个容器的静态 uid,在 alpine 上默认配置为 70,在标准图像上为 999)和 docker 限制(没有卷的 uid 转换)时,答案打动了我.

答案是在不对 docker-compose.yml 用户进行任何更改的情况下利用 Linux ACL - 只需保留默认的内部容器用户 ID。

mkdir -p ./data
sudo setfacl -m u:$(id -u):rwx -R ./data/
docker-compose up -d

docker-compose up -d
sudo setfacl -m u:$(id -u):rwx -R ./data/

创建数据卷目录的顺序无关紧要,只要在创建后设置ACL,您作为用户就可以递归访问它。您当然可以添加其他权限。

要检查谁有权访问数据文件夹,只需运行:

getfacl ./data
© www.soinside.com 2019 - 2024. All rights reserved.