使用绑定安装的主机目录和容器之间的Docker文件权限不匹配 [英] Docker file permissions mismatch between host dir and container using bind-mount

查看:152
本文介绍了使用绑定安装的主机目录和容器之间的Docker文件权限不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我的docker-compose堆栈由'postgresql','redis'和'Python api服务器'以及其他一些像opentracing等组成,但是问题区域仅限于上述内容.

  1. 我的撰写文件中的入口点是一个Shell脚本,它通过读取环境变量以及其他应做的事情来动态创建一些文件和文件夹.现在,这些文件的创建就像一个超级按钮一样,但是这些动态生成的文件的文件和文件夹权限变得很有趣.在macOS上,这些动态生成的文件和文件夹由运行docker-compose up的非root用户拥有.但是,在运行Ubuntu 19.01的Linux机器上,尽管Dockerfile明确对整个项目的文件夹进行了chown non-root-user:non-root-group并将活动用户设置为non-root-user

  2. ,但这些文件和文件夹仍归root所有
  3. postgres容器将其自身安装到给定的路径上,但是该目录的所有者不再是谁创建的,而是一些奇怪的systemd-coredump我猜这是因为Postgres Dockerfile上的userID和group映射到了我的用户名linux服务器?如果是,建议如何避免这种情况?

由于运行docker-compose up的非root用户无法在主机上保留文件和文件夹权限,因此Im遇到了permission denied问题.尽管chmod 777可以帮助解决该问题,但我相信chmod 777从未真正解决任何问题.

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

示例

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

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创建的. docker-compose up之后,所有者和组分别更改为system-coredumpdocker.

这是我的一部分: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上发生.

就像在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的友好名称,因此请确保主机用户和容器使用之间的用户名匹配,这样您便会好起来.

不相关的提示:

The problem

My docker-compose stack is comprised of 'postgresql', 'redis' and 'Python api server' along with a few others like opentracing etc., but the problem area is restricted to the before mentioned.

  1. The entrypoint in my compose file is a shell script that creates a few files and folders dynamically by reading the environment variables amongst the other things it is supposed to do. Now, the creation of these files work like a charm but the file and folder permissions of these dynamically generated files get interesting. On macos, these dynamically generated files and folders are owned by the non-root user who ran docker-compose up. But, on a linux machine running Ubuntu 19.01 these files and folders get owned by root despite Dockerfile explicitly doing a chown non-root-user:non-root-group to the whole project's folder and setting active USER as this non-root-user

  2. The postgres container mounts itself onto given path but the owner of that directory is no longer who created it but some strange systemd-coredump I guess this is because userID and group on Postgres' Dockerfile maps to this username on my linux server? If yes, what is the recommended way to avoid this?

Since the non-root user who ran docker-compose up is unable to retain file and folder permissions on host machine, Im running into permission denied issues. Whilst a chmod 777 helps get away with the problem, I believe chmod 777 never really solves any problem.

Re-iterating that all of this is a problem only on a Linux machine. On Macos running Docker-For-Mac, both pre-existing and dynamically generated files/folders retain the non-root logged in user as their owner and inside the container, the designated USER in Dockerfile remains the owner of all pre-existing (those that get transferred via COPY ) and newly generated dynamic files/folders.

Example

An example of change in file and folder ownership:

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/

From above, proton_db is where Postgres is supposed to mount onto. This folder was created initially by user - sparkle_deployment_2. After docker-compose up, the owner and group is changed to system-coredump and docker respectively.

Here is a slice of my: 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"]

And, here is my API server's 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

As you see, I'm doing a chown to explicitly have the directory owned by a non-root user. Despite this, when there are files/folders that get dynamically generated, they get root as their owner. And, this happens only on linux.

Win

Like in MacOS, I want the non-root host on linux machine to retain ownership of all pre-existing and dynamically generated files/folders hence not leading to any "permission denied" issues.

Plus the same non-root host on linux machine to retain ownership of the location where Postgres container volume gets mounted onto.

解决方案

Since you're bind-mounting the python container in docker-compose, the Dockerfile files and existing permissions are irrelevant. At runtime, it mounts pwd to /PROTON, so anything in the image at /PROTON is hidden and the container only sees the pwd on host.

The user in the container is a simple UID and GID number match to the host. For instance, use id command on host to get your UID and GID. For me, they are 1000 and 1000. You just need to ensure the user and group running in the container are that same UID/GID.

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

Now that your host user and container user UID/GID are the same, you'll notice that files created in pwd match the usernames of each user. Linux on host will look up the UID 1000 and see its your host user (for me it's bret) and if you do a docker-compose exec proton ls -al /PROTON you should notice it'll lookup user 1000 in the container and see proton. The usernames are just friendly names for the ID's, so just ensure they match between host user and container use and you'll be good.

Unrelated tips:

这篇关于使用绑定安装的主机目录和容器之间的Docker文件权限不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆