首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一种在linux和win中工作的非根名卷权限的数据提取方法

一种在linux和win中工作的非根名卷权限的数据提取方法
EN

Stack Overflow用户
提问于 2018-09-20 20:58:14
回答 1查看 685关注 0票数 5

我正在尝试一个简单的工作流程,但没有成功,我花了很多时间在SO和github上测试许多解决方案。对命名文件夹的权限和停靠中的更多一般权限卷是link1 link2 imho的噩梦。

因此,我从头开始,试图为我的用例创建一个简单的概念证明。

我要这个一般的工作流程:

  • windows和/或linux上的用户构建Dockerfile
  • 用户运行容器(如果可能的话,不要以root用户的身份)
  • 容器启动一个crontab,它每分钟在数据卷中运行脚本编写。
  • 用户(在linux或windows上)从数据卷(而不是root)获得结果,因为权限被正确映射。

我使用supercronic是因为它在没有root权限的容器中运行crontab。

Dockerfile

代码语言:javascript
复制
FROM artemklevtsov/r-alpine:latest as baseImage

RUN mkdir -p /usr/local/src/myscript/
RUN mkdir -p /usr/local/src/myscript/result

COPY . /usr/local/src/myscript/

WORKDIR /usr/local/src/myscript/

RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories
RUN apk --no-cache add busybox-suid curl

ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.$
    SUPERCRONIC=supercronic-linux-amd64 \
    SUPERCRONIC_SHA1SUM=9aeb41e00cc7b71d30d33c57a2333f2c2581a201

RUN curl -fsSLO "$SUPERCRONIC_URL" \
 && echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - \
 && chmod +x "$SUPERCRONIC" \
 && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
 && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic

CMD ["supercronic", "crontab"]

crontab文件:

代码语言:javascript
复制
* * * * * sh /usr/local/src/myscript/run.sh > /proc/1/fd/1 2>&1

run.sh脚本

代码语言:javascript
复制
#!/bin/bash

name=$(date '+%Y-%m-%d-%s')

echo "some data for the file" >> ./result/fileName$name

命令:

代码语言:javascript
复制
# create the volume for result, uid/gid option are not possible for windows 
docker volume create --name myTestVolume

docker run --mount type=volume,source=myTestVolume,destination=/usr/local/src/myscript/result test

docker run --rm -v myTestVolume:/alpine_data -v $(pwd)/local_backup:/alpine_backup alpine:latest tar cvf /alpine_backup/scrap_data_"$(date '+%y-%m-%d')".tar /alpine_data

当我这样做时,结果文件夹local_backup及其包含的文件具有root:root权限,因此启动该容器的用户不能访问这些文件。

有没有一种可行的解决方案,允许启动相同脚本的windows/linux/mac用户轻松地访问卷中的文件,而不存在权限问题?

编辑1 :

该策略首先描述了只在这里工作的绑定卷、和未命名的卷。我们使用entrypoint.sh来根据docker提供的信息来创建容器文件夹的uid/gid。

我复制粘贴修改后的Dockerfile:

代码语言:javascript
复制
FROM artemklevtsov/r-alpine:latest as baseImage

RUN mkdir -p /usr/local/src/myscript/
RUN mkdir -p /usr/local/src/myscript/result

COPY . /usr/local/src/myscript/

ENTRYPOINT [ "/usr/local/src/myscript/entrypoint.sh" ]

WORKDIR /usr/local/src/myscript/

RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories
RUN apk --no-cache add busybox-suid curl su-exec

ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.$
    SUPERCRONIC=supercronic-linux-amd64 \
    SUPERCRONIC_SHA1SUM=9aeb41e00cc7b71d30d33c57a2333f2c2581a201

RUN curl -fsSLO "$SUPERCRONIC_URL" \
 && echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - \
 && chmod +x "$SUPERCRONIC" \
 && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
 && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic

CMD ["supercronic", "crontab"]

The entrypoint.sh

代码语言:javascript
复制
#!/bin/sh
set -e

addgroup -g $GID scrap && adduser -s /bin/sh -D -G scrap -u $UID scrap

if [ "$(whoami)" == "root" ]; then
    chown -R scrap:scrap /usr/local/src/myscript/
    chown --dereference scrap "/proc/$$/fd/1" "/proc/$$/fd/2" || :
    exec su-exec scrap "$@"
fi

建造、发射、出口的程序:

代码语言:javascript
复制
docker build . --tag=test                                                       

docker run -e UID=1000 -e GID=1000 --mount type=volume,source=myTestVolume,destination=/usr/local/src/myscript/result test

 docker run --rm -v myTestVolume:/alpine_data -v $(pwd)/local_backup:/alpine_backup alpine:latest tar cvf /alpine_backup/scrap_data_"$(date '+%y-%m-%d')".tar /alpine_data

编辑2 :

对于Windows,使用停靠器工具箱和绑定卷我在上面找到了答案。我使用c:/Users/MyUsers文件夹进行绑定,它更简单。

代码语言:javascript
复制
docker run --name test -d -e UID=1000 -e GID=1000 --mount type=bind,source=/c/Users/myusers/localbackup,destination=/usr/local/src/myscript/result dockertest --name rflightscraps 

调查结果

  • 用废用户运行crontab
  • 本地用户的UID/GID映射到容器用户报废OK
  • 导出的数据仍然是根数据,不确定。
  • Windows / Linux半好 如果我使用绑定卷而不是命名卷,它就能工作。但是这不是想要的行为,我如何在Win/Linux上使用具有正确权限的命名卷.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-09 19:31:16

让我将答案分为Linux部分和Docker部分。为了解决这个问题,你需要理解这两个方面。

Linux部分

在Linux中,除了root之外,还可以轻松地以用户身份运行cron作业。

这可以通过使用与主机中相同的UID在docker容器中创建一个用户,并将crontab文件复制为/var/spool/cron/crontab/ user _name来实现。

来自man crontab

crontab是用于安装、卸载或列出用于驱动Vixie Cron中cron(8)守护进程的表的程序。每个用户都可以拥有自己的crontab,尽管这些是/var/spool/cron/crontabs,中的文件,但它们并不打算直接编辑。

因为Linux通过用户Id来标识用户,所以在坞内,UID将绑定到新创建的用户,而在主机中,UID将与主机用户绑定。

因此,您没有任何权限问题,因为这些文件属于host_user。现在,您应该已经理解了为什么我提到在主机中使用相同的UID创建用户。

码头零件

Docker认为所有目录(或层)都是UNION文件系统。每当您构建图像时,每个指令都会创建一个层,并且该层被标记为只读。这就是Docker容器不持久化数据的原因。因此,您必须显式地告诉docker,有些目录需要使用VOLUME关键字来持久化数据。

您可以不显式地提到卷就可以运行容器。如果这样做,那么docker守护进程就会认为它们是UFS,并重置权限。以保留对文件/目录的更改,包括所有权。应在Dockerfile中将相应的文件声明为卷。

来自联合文件系统

实际上,当容器启动时,它被移动到内存中,引导文件系统被卸载以释放initrd磁盘映像所使用的RAM。到目前为止,这看起来很像一个典型的Linux虚拟化堆栈。实际上,Docker下一层是根文件系统( rootfs ),位于引导文件系统的顶部。这个rootfs可以是一个或多个操作系统(例如Debian或Ubuntu文件系统)。Docker调用这些文件系统映像中的每一个。图像可以层叠在一起。下面的图像称为父图像,您可以遍历每个层,直到到达图像堆栈的底部,最后的图像被称为基本图像。最后,当容器从映像中启动时,Docker会将读写文件系统安装在下面任何层的顶部。这是我们希望我们的Docker容器运行的任何进程都将执行的地方。当Docker第一次启动容器时,初始读写层为空。当发生更改时,它们将应用于此层;例如,如果您想要更改文件,那么该文件将从下面的只读层复制到读写层。文件的只读版本仍然存在,但现在隐藏在副本下面。

示例:

让我们假设我们有一个名为host_user的用户。UID of host_user是1000。现在,我们将在Docker容器中创建一个名为docker_user的用户。所以我给他指定UID为1000。现在,docker_user在Docker容器中拥有的任何文件也属于host_user,如果host_user可以从主机(即通过卷)访问这些文件。

现在,您可以在没有任何权限问题的情况下与其他人共享绑定目录。您甚至可以在相应的目录上授予777权限,从而允许其他人编辑数据。否则,您可以保留755权限,允许其他人进行复制,但只允许所有者编辑数据。

我已经将目录声明为将更改作为卷持久化。这保留了所有的变化。注意,一旦您将目录声明为卷,则在构建将被忽略的同时对该目录进行进一步的更改,因为这些更改将位于不同的层中。因此,执行目录中的所有更改,然后将其声明为卷。

这是码头文件。

代码语言:javascript
复制
FROM alpine:latest
ARG ID=1000 
#UID as arg so we can also pass custom user_id
ARG CRON_USER=docker_user
#same goes for username

COPY crontab /var/spool/cron/crontabs/$CRON_USER
RUN adduser -g "Custom Cron User" -DH -u $ID $CRON_USER && \
    chmod 0600 /var/spool/cron/crontabs/$CRON_USER && \
    mkdir /temp && \
    chown -R $ID:$ID /temp && \
    chmod 777 /temp

VOLUME /temp
#Specify the dir to be preserved as Volume else docker considers it as Union File System

ENTRYPOINT ["crond", "-f", "-l", "2"]

这是crontab

代码语言:javascript
复制
* * * * * /usr/bin/whoami >> /temp/cron.log

塑造形象

代码语言:javascript
复制
docker build . -t test

创建新卷

代码语言:javascript
复制
docker volume create --name myTestVolume

与数据量一起运行

代码语言:javascript
复制
docker run --rm --name test -d -v myTestVolume:/usr/local/src/myscript/result test:latest

每当您将myTestVolume挂载到其他容器时,您都可以看到/usr/local/src/myscript/result下的数据属于UID 1000,如果在该容器中没有该UID或相应UID的用户名的话。

与绑定卷一起运行

代码语言:javascript
复制
docker run --rm --name test - -dv $PWD:/usr/local/src/myscript/result test:latest

当您执行ls -al /home/host_user/temp时,您将看到名为cron.log的文件是创建的,属于**host_user**

当您执行一个docker_userls -al /temp时,在ls -al /temp容器中也将拥有相同的内容。cron.log的内容将是docker_user

因此,您的有效Dockerfile应该是

代码语言:javascript
复制
FROM artemklevtsov/r-alpine:latest as baseImage

ARG ID=1000 

ARG CRON_USER=docker_user

RUN adduser -g "Custom Cron User" -DH -u $ID $CRON_USER && \
    chmod 0600 /var/spool/cron/crontabs/$CRON_USER && \
    echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && \
    apk --no-cache add busybox-suid curl && \
    mkdir -p /usr/local/src/myscript/result && \
    chown -R $ID:$ID /usr/local/src/myscript/result && \
    chmod 777 /usr/local/src/myscript/result

COPY crontab /var/spool/cron/crontabs/$CRON_USER

COPY . /usr/local/src/myscript/

VOLUME /usr/local/src/myscript/result
#This preserves chown and chmod changes.

WORKDIR /usr/local/src/myscript/

ENTRYPOINT ["crond", "-f", "-l", "2"] 

现在,每当您将数据/绑定卷附加到/usr/local/src/myscript/result时,它将由拥有UID 1000的用户拥有,并且在所有容器之间都具有相同的持久化,无论哪种容器安装了相同的卷,相应的用户以1000作为文件所有者。

请注意:为了与每个人共享,我已经授予了777 的权限。您可以根据您的方便性跳过Dockerfle中的这一步骤。

参考文献:

  1. Crontab手册
  2. 用户标识- Wiki
  3. 用户ID定义
  4. 关于存储驱动程序
  5. 联合文件系统
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52433220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档