摘要:问题产生原因最近在使用的时候经常遇到权限问题。如果权限不够,就会出现问题。从上图可以看到,主进程的拥有者是,可以读写任何文件,权限肯定没问题。要解决这个问题,其实就是让用户有权读写以及其中的文件。
问题产生原因
最近在使用docker的时候经常遇到权限问题。
通过这个stackoverflow回答,我明白了问题出现的主要原因:Docker在进行bind mount的时候,或者在进行COPY的时候,会保持文件的权限比特位(比如755)、owner ID(比如1000)、group ID(比如1000)与宿主机器上的来源文件相同。而【docker容器主进程的owner ID】(比如www-data(33))往往与【宿主机器上的文件的owner ID】(比如xiaoming(1000))不一样。如果【docker容器主进程的owner】没有权限读/写这个文件,那么bind-mounts和COPY到容器内的文件就不会产生我们预想的效果(比如配置文件无法被容器进程读取、写入)。
如果没有时间查看下面的最佳解决方案,可以试试这个简单粗暴的解决方案:在宿主机器上,通过sudo chmod -R 777 /path/to/dir将被挂载的目录的权限比特位设为777。这样,这个目录就能被任何用户读写,包括【docker容器主进程的owner】。但是这个方法可能会造成安全隐患,另外,git会将权限改动也视为文件变动(需要设置一下git来解决)。实例:判断问题 查看宿主上的权限信息
使用上一篇博客介绍的查看信息命令,在宿主机器上,检查被bind-mount或者被COPY的文件的权限信息:权限比特位(比如755)、owner ID(比如1000)、group ID(比如1000)。
查看容器内的权限信息通过以下命令,在指定容器内运行一个bash:
docker exec -it container_name /bin/bash
进入容器的bash以后,你就可以再次使用上一篇博客的查看信息命令,来查看容器中的进程、文件、用户信息了:
你可以验证一下被bind-mount、COPY的文件,它们的权限信息是否与宿主上的相同:权限比特位、owner ID、group ID。
然后,你应该通过ps aux来查看【容器主进程】的owner用户是谁(如果没有ps命令的话按照上一篇博客的指示来安装),这个owner就是需要访问文件的用户,这个用户的权限决定了这个进程是否有权访问【我们bind-mount、COPY到容器中的文件】。如果权限不够,就会出现问题。
从上图可以看到,主进程的拥有者是root,root可以读写任何文件,权限肯定没问题。但是主进程还创建了两个子进程,拥有者是www-data,这个用户有可能无法读写【被bind-mount或者COPY到容器内的文件】!
因此,现在我们需要检查www-data是否存在权限不足的问题,首先通过id username来查看这个用户的 user id、primary group id、加入的所有群组 的信息:
然后,使用stat或者ls -na命令,查看【被bind-mount或者COPY到容器内的文件】的权限信息:
上图的/codeigniter文件夹是我通过bind-mount挂载到容器内的。可以看到这个文件夹以及其中的文件的ownerId:groupId都是1000:1000,而www-data的ownerId:groupId是33:33。再结合这些文件的权限信息(比如-rw-rw-r--、drwx------),www-data只能读取其中一些文件,无法写入任何文件,/codeigniter/application/这个文件夹内的内容连访问都不行!
如上图,用stat也能看到同样的文件信息,只不过一次只能看到一个文件或文件夹的信息。
【容器主进程】有可能会创建其他的进程一起工作(比如上面的例子),如果是这样的话,你需要检查所有子进程都有权访问自己所需的文件。
上面的例子中,/codeigniter以及其中内容的权限比特位、owner ID、group ID都与我的宿主机器上的codeigniter文件夹相同(我登陆ubuntu的账户的userid就是1000)!保持文件的元数据(filesystem metadata)是docker的一个特点,也是一个坑点。
实例:解决问题既然知道了问题的成因,那么我们就可以想办法解决它了。
要解决这个问题,其实就是让www-data用户有权读写/codeigniter以及其中的文件。
有两个思路:
改变www-data的uid和gid,从33:33变成1000:1000。这样www-data就是这些文件的owner了,自然就有需要的权限了。改变uid和gid可以通过我上篇文章介绍的usermod命令。具体来说,就是在Dockerfile中加入这样一句:RUN usermod -u 1000 www-data && usermod -G 1000 www-data。(其实不需要改gid的,改uid就可以成为owner了)
改变容器内/codeigniter的权限信息,使得www-data(33:33)有权读写它:
通过chmod命令,在宿主机器上改变codeigniter文件夹的权限比特为777。这样,在bind-mount到容器里面以后它的权限也是777,因此任何用户都可以读写它的内容。这个方法要求修改开发环境,不太优雅。
在构建image时,将所有需要的文件COPY到镜像内,然后通过Run chmod 777 -R /codeigniter使得www-data获得读写权限,或者Run chown www-data:www-data -R /codeigniter使得www-data成为owner。
实际上COPY --chown=www-data:www-data ./codeigniter /codeigniter/就能一步将【被COPY的文件】的owner设置为容器内的某个用户。
我认为Run chmod 777 -R /codeigniter这个解决方案是最方便省事的。
但是我不太想chmod 777,我采用的是COPY --chown=www-data:www-data ./codeigniter /codeigniter/的方案,我喜欢这种方案,因为它只做恰到好处的修改,不多不少。要用好这个方案,我们需要知道被COPY的文件会被哪些进程访问、这些进程的onwer分别是谁。
使用这个方案以后的结果:
www-data用户的进程可以读写这些文件了!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/27332.html
摘要:同理,对于用户群组的删除,分别有和,它们的也是一模一样的。修改已有用户用户组修改已有用户用户组有关的工作,分别交给以下两个命令对于,比较常用的参数有,它们分别修改用户的主群组额外加入的群组用户。要切换当前用户所登陆的群组,使用命令。 查看信息 查看文件、文件夹的filesystem metadata # 查看**单个**文件、文件夹的权限信息 stat filename # 或者使用以...
摘要:可运行的和基础的指令已经在一个小型的仓库里。然后我们可以启动任何容器,到容器里面去对于一个教育示例,你可以这样做容器将把日志消息发送到,其实际是通过创建。你可以通过使用运行另外一个容器来查看日志,以及检查在里面的文件。 注:该文作者 jpetazzo,该文章的原文为 Multiple Docker containers logging to a single syslog 这...
摘要:发现问题之后,相应的解决方法也很简单把当前目录的拥有者赋值给,再启动容器就一切正常了。这时我们已经可以知道容器的本地数据卷中文件目录的权限是和宿主机上一致的,只是在容器和宿主机中可能映射为不同的用户组名称。 Volume数据卷是Docker的一个重要概念。数据卷是可供一个或多个容器使用的特殊目录,可以为容器应用存储提供有价值的特性: 持久化数据与容器的生命周期解耦:在容器删除之后数据卷...
阅读 2369·2021-11-18 10:07
阅读 2320·2021-09-22 15:59
阅读 3080·2021-08-23 09:42
阅读 2279·2019-08-30 15:44
阅读 1192·2019-08-29 15:06
阅读 2305·2019-08-29 13:27
阅读 1214·2019-08-29 13:21
阅读 1415·2019-08-29 13:13