Docker 使用绑定挂载的主机目录和容器之间的文件权限不匹配
Docker file permissions mismatch between host dir and container using bind-mount
The problem
我的 docker-compose 堆栈由 'postgresql'、'redis' 和 'Python api server' 以及其他一些如 opentracing 等组成,但问题区域仅限于前面提到的。
我的 compose 文件中的入口点是一个 shell 脚本,它通过读取环境变量以及它支持的其他内容来动态创建一些文件和文件夹os想做。现在,这些文件的创建就像一个魅力,但这些动态生成的文件的文件和文件夹权限变得有趣。在 macos 上,这些动态生成的文件和文件夹归 运行 docker-compose up
的非根用户所有。但是,在 linux 机器上 运行 Ubuntu 19.01 这些文件和文件夹归 root
所有,尽管 Dockerfile 明确地对 chown non-root-user:non-root-group
整个项目的文件夹并将活动用户设置为 non-root-user
postgres 容器将自身挂载到给定路径上,但该目录的所有者不再是创建它的人,而是某个 st运行ge systemd-coredump
我猜这是因为 Postgres' Docker 文件上的用户 ID 和组映射到我的 linux 服务器上的这个用户名?如果是,避免这种情况的推荐方法是什么?
由于 运行 docker-compose up
的非根用户无法在 host 机器上保留文件和文件夹权限,我 运行 进入 permission denied
问题。虽然 chmod 777
有助于解决问题,但我相信 chmod 777 从来没有真正解决任何问题。
重申所有这些只是 Linux 机器上的问题。在 Macos 运行 Docker-For-Mac 上,预先存在的和动态生成的 files/folders 都保留非 root 登录用户作为他们的所有者并在容器内,Docker 文件中的指定用户仍然是所有预先存在的所有者(通过 COPY
获得 t运行sferred 的 those)和新生成的动态 files/folders。
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 挂载的地方os。此文件夹最初由用户 - sparkle_deployment_2
创建。 docker-compose up
后,所有者和组分别更改为system-coredump
和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 服务器的 Docker 文件:
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 用户拥有的目录。尽管如此,当动态生成 files/folders 时,它们的所有者是 root
。而且,这只发生在 linux.
Win
像 MacOS 一样,我希望 linux 机器上的非 root host 保留所有预先存在的和动态生成的 files/folders 因此不会导致任何 "permission denied" 问题。
在 linux 机器上加上相同的非根 host 以保留 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
你应该注意到它会在容器并查看 proton
。 用户名只是 ID 的友好名称,因此只要确保它们在主机用户和容器使用之间匹配就可以了。
不相关的提示:
- 你可以 change the user that compose starts your container with,使用
user: username
,但如果它是你用 USER 放入 Dockerfile 的那个,那么在这种情况下就不需要了。
- 您的 Dockerfile COPY command can use chown 内联,为您节省一个步骤,space 在图像中:
COPY --chown=1000:1000 . /PROTON
, 或
COPY --chown=proton:proton . /PROTON
The problem
我的 docker-compose 堆栈由 'postgresql'、'redis' 和 'Python api server' 以及其他一些如 opentracing 等组成,但问题区域仅限于前面提到的。
我的 compose 文件中的入口点是一个 shell 脚本,它通过读取环境变量以及它支持的其他内容来动态创建一些文件和文件夹os想做。现在,这些文件的创建就像一个魅力,但这些动态生成的文件的文件和文件夹权限变得有趣。在 macos 上,这些动态生成的文件和文件夹归 运行
docker-compose up
的非根用户所有。但是,在 linux 机器上 运行 Ubuntu 19.01 这些文件和文件夹归root
所有,尽管 Dockerfile 明确地对chown non-root-user:non-root-group
整个项目的文件夹并将活动用户设置为non-root-user
postgres 容器将自身挂载到给定路径上,但该目录的所有者不再是创建它的人,而是某个 st运行ge
systemd-coredump
我猜这是因为 Postgres' Docker 文件上的用户 ID 和组映射到我的 linux 服务器上的这个用户名?如果是,避免这种情况的推荐方法是什么?
由于 运行 docker-compose up
的非根用户无法在 host 机器上保留文件和文件夹权限,我 运行 进入 permission denied
问题。虽然 chmod 777
有助于解决问题,但我相信 chmod 777 从来没有真正解决任何问题。
重申所有这些只是 Linux 机器上的问题。在 Macos 运行 Docker-For-Mac 上,预先存在的和动态生成的 files/folders 都保留非 root 登录用户作为他们的所有者并在容器内,Docker 文件中的指定用户仍然是所有预先存在的所有者(通过 COPY
获得 t运行sferred 的 those)和新生成的动态 files/folders。
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 挂载的地方os。此文件夹最初由用户 - sparkle_deployment_2
创建。 docker-compose up
后,所有者和组分别更改为system-coredump
和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 服务器的 Docker 文件:
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 用户拥有的目录。尽管如此,当动态生成 files/folders 时,它们的所有者是 root
。而且,这只发生在 linux.
Win
像 MacOS 一样,我希望 linux 机器上的非 root host 保留所有预先存在的和动态生成的 files/folders 因此不会导致任何 "permission denied" 问题。
在 linux 机器上加上相同的非根 host 以保留 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
你应该注意到它会在容器并查看 proton
。 用户名只是 ID 的友好名称,因此只要确保它们在主机用户和容器使用之间匹配就可以了。
不相关的提示:
- 你可以 change the user that compose starts your container with,使用
user: username
,但如果它是你用 USER 放入 Dockerfile 的那个,那么在这种情况下就不需要了。 - 您的 Dockerfile COPY command can use chown 内联,为您节省一个步骤,space 在图像中:
COPY --chown=1000:1000 . /PROTON
, 或COPY --chown=proton:proton . /PROTON