使用bind-mount时主机目录和容器之间的Docker文件权限不匹配

2024-03-15

问题

我的 docker-compose 堆栈由“postgresql”、“redis”和“Python api 服务器”以及其他一些组件(例如 opentracing 等)组成,但问题区域仅限于前面提到的区域。

  1. 我的撰写文件中的入口点是一个 shell 脚本,它通过读取环境变量以及它应该执行的其他操作来动态创建一些文件和文件夹。现在,这些文件的创建工作就像一个魅力,但这些动态生成的文件的文件和文件夹权限变得有趣。在 Macos 上,这些动态生成的文件和文件夹由运行的非 root 用户拥有docker-compose up。但是,在运行 Ubuntu 19.01 的 Linux 机器上,这些文件和文件夹的所有者是root尽管 Dockerfile 明确做了chown non-root-user:non-root-group到整个项目的文件夹并将活动用户设置为这样non-root-user

  2. postgres 容器将自身安装到给定路径,但该目录的所有者不再是创建它的人,而是一些奇怪的systemd-coredump我猜这是因为 Postgres 的 Dockerfile 上的 userID 和组映射到我的 Linux 服务器上的这个用户名?如果是,建议避免这种情况的方法是什么?

由于非root用户运行docker-compose up无法保留主机上的文件和文件夹权限,我遇到了permission denied问题。虽然一个chmod 777有助于解决问题,我相信 chmod 777 永远不会真正解决任何问题。

重申一下,所有这些都只是 Linux 机器上的问题。在运行 Docker-For-Mac 的 Macos 上,预先存在的和动态生成的文件/文件夹都保留非 root 登录用户作为其所有者,并且在容器内,Dockerfile 中指定的 USER 仍然是所有预先存在的(那些通过传输COPY)和新生成的动态文件/文件夹。

Example

文件和文件夹所有权更改的示例:

drwxrwxr-x 13 sparkle_deployment_2 sparkle_deployment_2 4096 Nov 21 01:00 PROTON/
drwx------ 19 systemd-coredump     docker               4096 Nov 21 01:00 proton_db/

从上面,proton_db是 Postgres 应该安装的地方。该文件夹最初由用户创建 -sparkle_deployment_2. After docker-compose up,所有者和组更改为system-coredump and docker分别。

这是我的一部分:docker-compose.yaml

version: "3.4"
services:
  pg:
    container_name: proton_postgres
    restart: always
    image: postgres
    environment:
      - POSTGRES_USER=${PG_USERNAME}
      - POSTGRES_PASSWORD=${PG_PASSWORD}
      - POSTGRES_DB=${PG_TARGET_DB}
    volumes:
      - ${PROTON_POSTGRES_VOLUME_MOUNT}:/var/lib/postgresql/data
    ports:
      - ${PG_TARGET_PORT}:${PG_TARGET_PORT}
  redis:
    container_name: proton_redis
    restart: always
    image: redis
    volumes:
      - ${PROTON_REDIS_VOLUME_MOUNT}:/data
    ports:
      - ${REDIS_TARGET_PORT}:${REDIS_TARGET_PORT}
  proton:
    container_name: proton
    restart: always
    image: proton_stretch
    ports:
      - ${PROTON_TARGET_PORT}:${PROTON_TARGET_PORT}
    expose:
      - ${PROTON_TARGET_PORT}
    volumes:
      - .:/PROTON
      - ${PROTON_SQLITE_VOLUME_MOUNT}:/PROTON/proton-db
    depends_on:
      - pg
      - redis
    entrypoint: ["./proton.sh"]

而且,这是我的 API 服务器的 Dockerfile:

FROM python:3.7.3-stretch

RUN apt-get update
RUN apt-get install bash
RUN apt-get install -y gcc g++ unixodbc-dev

RUN groupadd -g proton_user_group
RUN useradd -G proton_user_group default_proton_user

RUN mkdir -p /PROTON
WORKDIR /PROTON
COPY . /PROTON

RUN python3 -m pip install -r requirements.txt --no-cache-dir

RUN chown -R default_proton_user:proton_user_group /PROTON
USER default_proton_user

EXPOSE 3000/tcp

如你所见,我正在做一个chown明确让非 root 用户拥有该目录。尽管如此,当存在动态生成的文件/文件夹时,它们会得到root作为他们的主人。而且,这种情况只发生在 Linux 上。

Win

就像在 MacOS 中一样,我希望 Linux 计算机上的非 root 主机保留所有预先存在的和动态生成的文件/文件夹的所有权,因此不会导致任何“权限被拒绝”问题。

再加上 Linux 计算机上的相同非 root 主机,以保留 Postgres 容器卷安装位置的所有权。


由于您在 docker-compose 中绑定安装了 python 容器,因此 Dockerfile 文件和现有权限是无关的。在运行时,它会挂载pwd到 /PROTON,因此 /PROTON 处图像中的任何内容都被隐藏,容器只能看到pwd在主机上。

容器中的用户是与主机匹配的简单UID和GID号。例如,使用id主机上的命令获取您的 UID 和 GID。对我来说,它们是 1000 和 1000。您只需确保容器中运行的用户和组具有相同的 UID/GID。

RUN groupadd --gid 1000 proton \
  && useradd --uid 1000 --gid proton --create-home proton

现在您的主机用户和容器用户 UID/GID 相同,您会注意到创建的文件pwd匹配每个用户的用户名。主机上的 Linux 将查找 UID 1000 并查看它是您的主机用户(对我来说是bret)如果你做了一个docker-compose exec proton ls -al /PROTON你应该注意到它会在容器中查找用户 1000 并看到proton. 用户名只是 ID 的友好名称,因此只需确保它们在主机用户和容器使用之间匹配即可。

不相关的提示:

  • You can 更改 compose 启动容器的用户 https://docs.docker.com/compose/compose-file/#domainname-hostname-ipc-mac_address-privileged-read_only-shm_size-stdin_open-tty-user-working_dir, using user: username,但如果它是您与 USER 一起放入 Dockerfile 中的文件,则在这种情况下不需要。
  • Your Dockerfile COPY command can use chown http://COPY%20.%20/PROTON inline, to save you a step and space in image:
    • COPY --chown=1000:1000 . /PROTON , or
    • COPY --chown=proton:proton . /PROTON
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用bind-mount时主机目录和容器之间的Docker文件权限不匹配 的相关文章

随机推荐