博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【docker】 bind-mount或者COPY时需要注意 用户、文件权限 的问题
阅读量:5947 次
发布时间:2019-06-19

本文共 2607 字,大约阅读时间需要 8 分钟。

问题产生原因

最近在使用docker的时候经常遇到权限问题。

通过这个,我明白了问题出现的主要原因:Docker在进行的时候,或者在进行的时候,会保持文件的权限比特位(比如755)、owner ID(比如1000)、group ID(比如1000)与宿主机器上的来源文件相同。而【docker容器主进程的owner ID】(比如www-data(33))往往与【宿主机器上的文件的owner ID】(比如xiaoming(1000))不一样。如果【docker容器主进程的owner】没有权限读/写这个文件,那么bind-mountsCOPY到容器内的文件就不会产生我们预想的效果(比如配置文件无法被容器进程读取、写入)。

如果没有时间查看下面的最佳解决方案,可以试试这个简单粗暴的解决方案:在
宿主机器上,通过
sudo chmod -R 777 /path/to/dir
被挂载的目录的权限比特位设为777。这样,这个目录就能被任何用户读写,包括【docker容器主进程的owner】。但是这个方法可能会造成安全隐患,另外,git会将权限改动也视为文件变动(需要 来解决)。

实例:判断问题

查看宿主上的权限信息

使用介绍的查看信息命令,在宿主机器上,检查被bind-mount或者被COPY的文件的权限信息:权限比特位(比如755)、owner ID(比如1000)、group ID(比如1000)。

查看容器内的权限信息

通过以下命令,在指定容器内运行一个bash:

docker exec -it container_name /bin/bash

进入容器的bash以后,你就可以再次使用的查看信息命令,来查看容器中的进程、文件、用户信息了:

  1. 你可以验证一下被bind-mount、COPY的文件,它们的权限信息是否与宿主上的相同:权限比特位、owner ID、group ID。
  2. 然后,你应该通过ps aux来查看【容器主进程】的owner用户是谁(如果没有ps命令的话按照的指示来安装),这个owner就是需要访问文件的用户,这个用户的权限决定了这个进程是否有权访问【我们bind-mount、COPY到容器中的文件】。如果权限不够,就会出现问题。

    • 从上图可以看到,主进程的拥有者是rootroot可以读写任何文件,权限肯定没问题。但是主进程还创建了两个子进程,拥有者是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-dataownerId:groupId33: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以及其中的文件

有两个思路:

  1. 改变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了)
  2. 改变容器内/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用户的进程可以读写这些文件了!

转载地址:http://shbxx.baihongyu.com/

你可能感兴趣的文章
三级联动效果
查看>>
Sprite和UI Image的区别
查看>>
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql/mysql.sock' (2)
查看>>
python练习笔记——丑数的计算
查看>>
OpenCV + python 实现人脸检测(基于照片和视频进行检测)
查看>>
XSS 前端防火墙 —— 天衣无缝的防护
查看>>
Node.js umei图片批量下载Node.js爬虫1.00
查看>>
客户端拖动控件封装(让拖动变得更简单)
查看>>
linux下IPTABLES配置详解
查看>>
Sharepoint学习笔记—习题系列--70-576习题解析 -(Q131-Q134)
查看>>
iOS边练边学--iOS中的(ARC下)单粒模式(GCD实现)
查看>>
php get_magic_quotes_gpc()函数用法介绍
查看>>
SQL to Java code for Elasticsearch
查看>>
Java RMI之HelloWorld程序以及相关的安全管理器的知识
查看>>
FlatBuffers
查看>>
美团HD(5)-选择城市
查看>>
$.when()方法监控ajax请求获取到的数据与普通ajax请求回调获取到的数据的不同
查看>>
pthread_mutex_t
查看>>
LR11.0 下载及破解
查看>>
Java基础-绘图技术
查看>>