【问题标题】:why doesn't chown work in Dockerfile? [closed]为什么 chown 在 Dockerfile 中不起作用? [关闭]
【发布时间】:2014-10-01 15:50:37
【问题描述】:

我的 Dockerfile 创建一个目录,chown's it,然后列出该目录。该目录仍归根用户所有。这是为什么呢?

这里是 Dockerfile:

FROM ubuntu:precise
RUN useradd -d /home/testuser -m -s /bin/bash testuser
RUN mkdir -p /var/local/testrunner/logs
VOLUME ["/var/local/testrunner/logs"]
RUN grep testuser /etc/passwd
RUN grep root /etc/passwd
RUN chown -R testuser:testuser /var/local/testrunner/logs
RUN ls -ld /var/local/testrunner/logs 

这是“docker build”的输出:

Sending build context to Docker daemon 10.24 kB
Sending build context to Docker daemon 
Step 0 : FROM ubuntu:precise
 ---> ab8e2728644c
Step 1 : RUN useradd -d /home/testuser -m -s /bin/bash testuser
 ---> Using cache
 ---> 640f12671c86
Step 2 : RUN mkdir -p /var/local/testrunner/logs
 ---> Using cache
 ---> bf7756fd5b1f
Step 3 : VOLUME ["/var/local/testrunner/logs"]
 ---> Using cache
 ---> 65c73ee76c20
Step 4 : RUN grep testuser /etc/passwd
 ---> Using cache
 ---> db72fff0b965
Step 5 : RUN grep root /etc/passwd
 ---> Running in ebff78df7a9a
root:x:0:0:root:/root:/bin/bash
 ---> ead0ff704a59
Removing intermediate container ebff78df7a9a
Step 6 : RUN chown -R testuser:testuser /var/local/testrunner/logs
 ---> Running in c925f67b2ab4
 ---> 253132be935e
Removing intermediate container c925f67b2ab4
Step 7 : RUN ls -ld /var/local/testrunner/logs
 ---> Running in 978bc66aa47e
drwxr-xr-x 2 root staff 4096 Oct  1 15:15 /var/local/testrunner/logs

Docker 版本 1.2.0,构建 fa7b24f

主机运行 Ubuntu 12.04,但使用 3.13.0-36 通用内核。

【问题讨论】:

标签: docker chown


【解决方案1】:

回答我自己的问题:它被宣布为一卷。取出VOLUME指令,chown生效。

更重要的是,如果您在运行 chown 之后声明卷,则 chown 设置仍然有效。

【讨论】:

  • "如果您在运行 chown 后声明音量,则 chown 设置仍然有效" 这只是回答了让我难过两天的问题。谢谢!
  • 回答自己:这里的解释对我来说很有意义container-solutions.com/2014/12/understanding-volumes-docker
  • 上面那篇文章的重要一点:“[当在修改卷的RUN 命令之后指定VOLUME 时],docker 足够聪明,可以复制镜像中存在的任何文件卷装入卷并正确设置所有权。如果您为卷指定主机目录,则不会发生这种情况(以免意外覆盖主机文件)。"
  • @MichaelHärtl 链接的解释更新 URL 为:blog.container-solutions.com/understanding-volumes-docker
  • 我没有在我的 dockerfile 上声明任何 VOLUME 并且仍然有这个问题...... :-(
【解决方案2】:

对于任何在没有卷的情况下遇到此问题的人,我发现了一个复杂的解决方法。

问题:

用一个简单的Dockerfile如下:

FROM ubuntu:16.04
RUN useradd -m -d /home/new_user new_user
COPY test_file.txt /home/new_user
RUN chown -R new_user:new_user /home/new_user
CMD ls -RFlag /home

运行后:

echo "A file to test permissions." > test_file.txt
docker build -t chown-test -f Dockerfile .
docker run --rm -it chown-test

输出是:

/home:
total 12
drwxr-xr-x 1 root 4096 Jun 15 21:37 ./
drwxr-xr-x 1 root 4096 Jun 15 21:39 ../
drwxr-xr-x 1 root 4096 Jun 15 21:39 new_user/

/home/new_user:
total 24
drwxr-xr-x 1 root 4096 Jun 15 21:39 ./
drwxr-xr-x 1 root 4096 Jun 15 21:37 ../
-rw-r--r-- 1 root  220 Aug 31  2015 .bash_logout
-rw-r--r-- 1 root 3771 Aug 31  2015 .bashrc
-rw-r--r-- 1 root  655 Jul 12  2019 .profile
-rw-r--r-- 1 root   28 Jun 11 19:48 test_file.txt

如您所见,文件所有权(例如 test_file.txt)仍与用户 root 相关联。

解决方案:

我发现如果我在chown命令中使用数字UID,我可以更改所有权,但前提是UID不是1000。所以我在new_user的UID上加了1,然后更改了所有权.

FROM ubuntu:16.04
RUN useradd -m -d /home/new_user new_user
# change the uid of new_user to ensure it has whatever it was assigned plus 1 (e.g. if UID was 1000, now it'll be 1001)
RUN id -u new_user | awk '{print $1+1}' | xargs -I{} usermod -u {} new_user
COPY test_file.txt /home/new_user
RUN id -u new_user | xargs -I{} chown -R {}:{} /home/new_user
CMD ls -RFlag /home

运行后:

echo "A file to test permissions." > test_file.txt
docker build -t chown-test -f Dockerfile .
docker run --rm -it chown-test

输出是:

/home:
total 12
drwxr-xr-x 1 root 4096 Jun 15 21:37 ./
drwxr-xr-x 1 root 4096 Jun 15 21:37 ../
drwxr-xr-x 1 1001 4096 Jun 15 21:37 new_user/

/home/new_user:
total 24
drwxr-xr-x 1 1001 4096 Jun 15 21:37 ./
drwxr-xr-x 1 root 4096 Jun 15 21:37 ../
-rw-r--r-- 1 1001  220 Aug 31  2015 .bash_logout
-rw-r--r-- 1 1001 3771 Aug 31  2015 .bashrc
-rw-r--r-- 1 1001  655 Jul 12  2019 .profile
-rw-r--r-- 1 1001   28 Jun 11 19:48 test_file.txt

我不确定为什么我首先会遇到这个问题。但是,由于其他人似乎遇到了这个问题,我想我会发布我的解决方法。我的用例是创建一个为 jupyter notebook 服务的 docker 容器。我创建了一个非 root 用户来为笔记本提供服务。

【讨论】:

  • 使用 usermod 文件手动修改 UID 是一个丑陋的 hack。您可以在创建时使用 useradd -u 1001 指定 UID
【解决方案3】:

此博客http://container42.com/2014/11/03/docker-indepth-volumes/ 详细解释了此行为。

Dockerfile 中的每条指令都会创建一个新容器。该指令对该容器进行一些更改并成为一个新层。在对实际容器文件系统进行 VOLUME 指令之前对“/var/local/testrunner/logs”所做的更改。但是,在 VOLUME 指令之后,目录“/var/local/testrunner/logs”是挂载的目录。在 VOLUME 指令之后对该目录所做的更改将应用​​于已挂载的目录,而不是实际的容器文件系统。

【讨论】:

    【解决方案4】:

    根据我的经验,chown 在挂载到 root (VOLUME /test) 时不起作用。使用非根位置 (VOLUME /var/test)。

    【讨论】:

      【解决方案5】:

      对于 Alpine Linux 用户,我必须在我试图拥有的工作区中执行 chown -R root .。这必须在 dockerfile 的CMD 中完成,因为我相信卷挂载可能会在挂载时覆盖文件

      【讨论】:

        【解决方案6】:

        如果你使用volumen,你可以在运行后设置权限,像这样:

        docker exec -u 0 my-container chmod -R 700 /my/path
        docker exec -u 0 my-container chown -R my-non-user-root /my/path
        

        【讨论】:

          猜你喜欢
          • 2021-01-18
          • 1970-01-01
          • 2013-02-04
          • 1970-01-01
          • 1970-01-01
          • 2018-02-15
          • 2018-02-15
          • 2017-12-13
          • 1970-01-01
          相关资源
          最近更新 更多