===================================================================

在刚开始使用docker volume挂载数据卷的时候,经常出现没有权限的问题。

这里通过遇到的问题来理解docker容器用户uid的使用,以及了解容器内外uid的映射关系。

遇到的问题

本地有一个node的项目需要编译,采用docker来run npm install.

sudo docker run -it --rm  --name ryan  \
-v `pwd`:`pwd` \
-w `pwd` node \
npm install --registry=https://registry.npm.taobao.org

可以看到,install之后,node_modules文件的权限变成root了。那么,作为使用者的我们就没有权限去删除这个文件了。

为什么docker输出的文件权限会是root?

原因

Docker容器运行的时候,如果没有专门指定user, 默认以root用户运行。我们的node镜像的Dockerfile里没有指定user.

容器里的执行用户的id是0,输出文件的权限也是0.

以下参考Understanding how uid and gid work in Docker containers

容器共享宿主机的uid

首先了解uid,gid的实现。Linux内核负责管理uid和gid,并通过内核级别的系统调用来决定是否通过请求的权限。

比如,当一个进程尝试去写文件,内核会检查创建这个进程的的user的uid和gid,来决定这个进程是否有权限修改这个文件。

这里没有使用username,而是uid。

当docker容器运行在宿主机上的时候,仍然只有一个内核。容器共享宿主机的内核,所以所有的uid和gid都受同一个内核来控制。

那为什么我容器里的用户名不一定和宿主内核一样呢? 比如,superset容器的用户叫做superset, 而本机没有superset这个用户。这是因为username不是Linux kernel的一部分。简单的来说,username是对uid的一个映射。

然而,权限控制的依据是uid,而不是username。

That’s because the username (and group names) that show up in common
linux tools aren’t part of the kernel, but are managed by external tools
(/etc/passwd, LDAP, Kerberos, etc). So, you might see different
usernames, but you can’t have different privileges for the same uid/gid,
even inside different containers

如果不指定user,容器内部默认使用root用户来运行

我们继续使用node镜像, 你可以在github查看Dockerfile. 里面创建了一个

uid为1000的用户node,但没指定运行user。

docker run -d --rm --name ryan node sleep infinity

我执行的用户为ryan(uid=1000), 让容器后台执行sleep程序。

可以看到,容器外执行sleep的进程的用户是root。容器内部的用户也是0(root). 虽然执行docker run的用户是ryan.

也就是说,我一个普通用户居然可以以root的身份去执行一个命令。看起来挺恐怖的样子。

容器内部用户的权限与外部用户相同

权限是通过uid来判断的。接下来测试,相同uid的用户可以修改归属于这个uid的文件。

宿主机有一个用户ryan:

刚才使用的node镜像的Dockerfile也定义了1000的用户node:

我们在本地写一个文件a, 归属用户ryan

然后,通过volume挂载的方式,指定运行user为1000, 启动容器node:

docker run -d --rm --name test -u 1000:1000 -v $(pwd):/tmp node sleep infinity

可以看到, 容器外执行sleep的进程,user是ryan(另一个sleep进行是前面的root用户执行的实例,没删除)。

即,docker run -u 可以指定宿主机运行docker命令的用户, -u指定的uid就是docker实际运行的进程拥有者

接下来去容器内部,看看能不能修改挂载的文件。

可以看到,我们挂载的文件a在容器内部显示owner是node,即uid=1000的用户。并且有权限查看和修改。

然后,我们写一个文件b,在容器内部,这个b自然属于uid=1000的node。来看看容器外:

同样的,容器外显示b从属于uid=1000的用户ryan,并且有权限查看和修改。

如此,可以证明容器内外共享uid和对应的权限。

一定要确保容器执行者的权限和挂载数据卷对应

本文最初的问题就是因为容器执行者和挂载数据卷的权限不同。容器内部运行是uid=0的用户,数据卷从属与uid=1000的ryan。最终导致容器写入数据卷的文件权限升级为root, 从而普通用户无法访问。

如果挂载了root的文件到容器内部,而容器内部执行uid不是0,则报错没有权限。我在挂载npm cache的时候遇到了这个问题,于是有了本文。

一个更加明显的demo

上面的demo恰好宿主机器和容器都存在一个uid=1000的用户,于是很和谐的实现了文件权限共享。接下来测试一个更加明显的demo。

宿主机器和容器都没有uid=1111, 我们以1111来执行容器:

docker run -d --rm --name demo -u 1111:1111 -v $(pwd):/tmp node sleep infinity

  1. 当前数据卷有文件a和dir any_user. 文件a归属与uid=1000, dir any_user任何人可以写
  2. 运行容器,并以uid=1111执行
  3. 登录容器内部,查看数据卷,发现文件a和dir any_user都归属于uid=1000的node(uid映射)
  4. 由于容器内部没有uid=1111的用户,所以显示I have no name!, 没有username,没有home。
  5. 在容器内部执行数据卷的写操作,提示没权限。(因为数据卷的权限是uid=1000)
  6. 在容器内部写入一个文件到公共数据区(777).

接下来看看容器外的表现:

  • 数据文件确实有被写入,内容可读
  • 容器写入的文件的权限都是1111的uid。由于宿主机没有这个用户,直接显示uid
  • 查看进程,可以发现容器的进程也是1111

即-u指定容器内部执行的用户,以及容器外在宿主机进程的用户,同样容器写到数据卷的权限也由此指定。

如此,这个demo更容易理解容器内外的uid的对应关系。理解了以后我们挂载数据卷的时候就不会出现权限问题了。

由于安全问题,通常也是建议不用使用root来运行容器的。

参考

=================================================================

原文作者:Ryan Miao
原文链接:https://www.cnblogs.com/woshimrf/p/understand-docker-uid.html

本文采用 BY-NC-SA 许可协议。转载请注明出处!

【转载】 docker挂载volume的用户权限问题,理解docker容器的uid的更多相关文章

  1. docker挂载volume的用户权限问题,理解docker容器的uid

    docker挂载volume的用户权限问题,理解docker容器的uid 在刚开始使用docker volume挂载数据卷的时候,经常出现没有权限的问题. 这里通过遇到的问题来理解docker容器用户 ...

  2. win10专业版Hyper-v下Docker挂载volume的方式使用Gitlab(汉化版)保存资料数据(使用外部redis)

    目录 话题 (191) 笔记 (137) 资料区 (2) 评价 (33) 介绍 讨论区 话题 win10专业版Hyper-v下Docker挂载volume的方式使用Gitlab(汉化版)保存资料数据( ...

  3. docker managed volume - 每天5分钟玩转 Docker 容器技术(40)

    docker managed volume 与 bind mount 在使用上的最大区别是不需要指定 mount 源,指明 mount point 就行了.还是以 httpd 容器为例: 我们通过 - ...

  4. Docker:从引擎和运行框架理解Docker(3)

    Docker是GO语言编写的. 1.Docker发挥的作用: 1.快速.一致.标准化的交付应用.从开发.测试.到部署交付到成产环境都可以使用docker命令处理image到不同的环境 2.部署和扩展: ...

  5. 多个docker 挂载VOLUME的心得

    假如有一个mysql镜像 在Dockerfile中制定VOLUME /var/lib/mysql 那么当执行: docker run -d -e MYSQL_ROOT_PASSWORD=root -- ...

  6. Docker -v 对挂载的目录没有权限 Permission denied

    1.问题 今天在使用docker挂载redis的时候老是报错 docker run -v /home/redis/redis.conf:/usr/local/etc/redis/redis.conf ...

  7. 用一个实际例子理解Docker volume工作原理

    要了解Docker Volume,首先我们需要理解Docker文件系统的工作原理.Docker镜像是由多个文件系统的只读层叠加而成.当一个容器通过命令docker run启动时,Docker会加载只读 ...

  8. docker挂载本地目录的方法总结

    docker挂载本地目录的方法总结: Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定. 譬如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录, ...

  9. Docker源码分析(四):Docker Daemon之NewDaemon实现

    1. 前言 Docker的生态系统日趋完善,开发者群体也在日趋庞大,这让业界对Docker持续抱有极其乐观的态度.如今,对于广大开发者而言,使用Docker这项技术已然不是门槛,享受Docker带来的 ...

  10. 【docker专栏8】使用IDEA远程管理docker镜像及容器服务

    使用命令行的方式管理服务器镜像及容器是运维人员最常用的方式,但是有的时候我们不得不远程操作docker或者是面向对docker并不熟悉的技术人员提供能力(配置管理员.测试人员),这种情况下图形界面就有 ...

随机推荐

  1. freemarker模板替换生成word

    工具类 public static void createWord(Map<String,Object> dataMap, String templateName, String file ...

  2. 天翼云centos7.6安装redis6.2.6

    以下部分的具体略: 1.wget获取源码 2.make 这里重点说下,如何使用 utils/install_server.sh脚本 使用install_service.sh添加服务 有了这个脚本,那么 ...

  3. [ABC347C] Ideal Holidays题解

    [ABC347C] Ideal Holidays题解 原题传送门 原题传送门(洛谷) ​ 题意翻译: ​ 在 \(AtCoder\) 王国中,一个周有 \(A+B\) 天.其中在一周中, \([1,A ...

  4. 记一次难忘的json反序列化问题排查经历

    前言 最近我在做知识星球中的商品秒杀系统,昨天遇到了一个诡异的json反序列化问题,感觉挺有意思的,现在拿出来跟大家一起分享一下,希望对你会有所帮助. 案发现场 我最近在做知识星球中的商品秒杀系统,写 ...

  5. Nuxt3 的生命周期和钩子函数(七)

    title: Nuxt3 的生命周期和钩子函数(七) date: 2024/6/30 updated: 2024/6/30 author: cmdragon excerpt: 摘要:文章阐述了Nuxt ...

  6. 单片机升级,推荐此79元双核A7@1.2GHz国产平台的8个理由

    含税79元即可运行Linux操作系统 对于嵌入式软件开发者而言,单片机令人最痛苦的莫过于文件操作.79元T113-i工业核心板(基于全志国产处理器,国产化率100%)可运行Linux操作系统,可使用L ...

  7. ScreenToGif:一款开源免费且好用的录屏转Gif软件

    ScreenToGif介绍 GitHub上的介绍:此工具允许您记录屏幕的选定区域.来自网络摄像头的实时提要或来自草图板的实时绘图.之后,您可以编辑动画并将其保存为 gif.apng.视频.psd 或 ...

  8. 3.3 Y86-64的顺序实现

    将处理组织成阶段 为了实现流水线处理机制,要将指令组织成某个特殊的阶段序列,所有的指令遵循统一的序列,不同阶段放在不同硬件上进行处理.下面是对各阶段的简述. 取指(fetch):取指阶段从内存读取指令 ...

  9. 深度解读昇腾CANN模型下沉技术,提升模型调度性能

    本文分享自华为云社区<深度解读昇腾CANN模型下沉技术,提升模型调度性能>,作者:昇腾CANN. AI模型的运行通常情况下需要CPU和NPU(昇腾AI处理器)等AI专用处理器协同工作,CP ...

  10. Service Mesh Summit 回顾 | 轻舟服务网格的无侵入增强 Istio 经验

    在云原生社区近日主办的 Service Mesh Summit 2022 服务网格峰会上,网易数帆云原生技术专家方志恒分享了轻舟服务网格无侵入增强 Istio 的经验,本文据此次分享整理,介绍了对无侵 ...