介绍两种从 Docker 容器写入卷时的文件权限处理方式-hosts文件修改

介绍两种从 Docker 容器写入卷时的文件权限处理方式

每周一、三、五,与您不见不散!


容器常常用作原生安装工具的替代品。在主机上使用具有所需版本的容器要比使用过时的工具好的多。但是,只要容器与主机系统进行交互,文件会留下错误或损坏的权限。幸运的是,解决该问题的方法并不需要使用脚本。


问题描述


当容器挂载一个本地目录并将文件写入其中时,其所有权由容器内的用户决定:

nicholas@host:~/source$ mkdir source

nicholas@host:~/source$ docker run -it --rm --volume $(pwd):/source --workdir /source ubuntu

root@a031d11c9515:/source# mkdir subdir

root@a031d11c9515:/source# touch subdir/newfile

root@a031d11c9515:/source# exit

exit

nicholas@host:~/source$ ls -lR

.:

total 4

drwxr-xr-x 2 root root 4096 Jul 16 19:35 subdir

./subdir:

total 0

-rw-r--r-- 1 root root 0 Jul 16 19:35 newfile

nicholas@host:~/source$ rm -rf subdir/

rm: cannot remove 'subdir/newfile': Permission denied

另外,您还可能无法删除这些目录和拥有错误所有权的文件。


解决方案1:从容器中删除


一个非常常见的解决方案是从容器内部更改文件和目录的所有权:

nicholas@host:~/source$ docker run -it --rm --volume $(pwd):/source --workdir /source ubuntu

root@d1c3bee8bb2b:/source# ls -al

total 12

drwxrwxr-x 3 1000 1004 4096 Jul 16 19:35 .

drwxr-xr-x 1 root root 4096 Jul 16 19:39 ..

drwxr-xr-x 2 root root 4096 Jul 16 19:35 subdir

root@d1c3bee8bb2b:/source# chown 1000:1000 subdir/ -R

root@d1c3bee8bb2b:/source# ls -l

total 4

drwxr-xr-x 2 1000 1000 4096 Jul 16 19:35 subdir

root@d1c3bee8bb2b:/source# exit

exit

nicholas@host:~/source$ ls -l

total 4

drwxr-xr-x 2 nicholas lpadmin 4096 Jul 16 19:35 subdir

nicholas@host:~/source$

这种方法的缺点是需要添加额外的逻辑,以及您需要知道运行该容器用户的用户 ID 和组 ID。


解决方案2:创建拥有正确所有权的文件


第二种解决方案更简洁,它将使用容器内的正确所有权创建文件和目录。Docker 提供了一个参数来设置容器内用户的用户 ID 和组 ID:

nicholas@host:~/source$ docker run -it --rm --volume $(pwd):/source --workdir /source --user $(id -u):$(id -g) ubuntugroups: cannot find name for group ID 1004I have no name!@bf7f355f3b65:/source$ touch newfileI have no name!@bf7f355f3b65:/source$ exitexitnicholas@host:~/source$ ls -ltotal 4-rw-r--r-- 1 nicholas nicholas 0 Jul 16 19:42 newfiledrwxr-xr-x 2 nicholas lpadmin 4096 Jul 16 19:35 subdirnicholas@host:~/source$

这种方法可以很好的帮您解决用户 ID 和组 ID 的错误。

请注意,出于安全目的,在容器内以 root 身份运行是最糟糕的做法。Dockerfile 应始终使用 USER 指令从而避免直接使用 root 权限。

推荐阅读