• Linux内核又躺枪 之《docker挂载volume的权限问题》


    我对docker不太成熟的认知!写的不好望指出!互相学习、交流!

    对docker的认知

    为什么说Linux内核又躺枪了,日常甩锅,只能把锅甩给Linux 内核了,哈哈哈..

    docker依赖于Linux的两个内核特性:

    Namespaces - 命名空间
    Control groups(cgroups)- 控制组

    Namespaces

    命名空间提供了一种系统资源的隔离,包括了文件系统、网络、进程等。

    docker有以下5种命名空间:

    PID:进程隔离
    NET:网络管理接口
    IPC:管理跨进程通信访问
    MNT:管理挂载点
    UTS:隔离内核和版本标识

    Control groups

    这是Linux内核提供的一种可以限制,记录,隔离物理进程组的机制。他提供了以下功能:

    资源限制
    优先级设定
    资源计量
    资源控制

    docker 基本能力

    Namespaces和Control groups带给了容器下面的能力:
    
    文件系统的隔离:每个容器都有自己的root文件系统
    进程隔离:每个容器都运行在自己的进程环境中
    网络隔离:每个容器间虚拟网络接口和ip地址都是分开的
    资源隔离和分组:Control groups可以将CPU和内存之类的资源独立分配给每个docker容器

    使用场景

    我们在使用docker容器的时候,经常要给容器里面挂载本地服务器目录,从而实现某个文件在宿主机和容器内部都可以访问的效果。
    例如:在容器内部进行删除、添加、复制、剪切、读写文件,说白了就是访问挂载的卷

    问题介绍 - docker挂载volume的权限问题

    报错:一般都是在进行一系列操作抛出权限问题

    touch: cannot touch '/var/jenkins/copy_file.log' : Permission denied
    can not write to '/var/jenkins/copy_file.log' . Wrong volume permission?
    # 这是在说你没有权限在这个目录里面创建文件,以及写东西

    问题根由

    因为容器共享宿主机的uid,如果不指定user,容器内部默认使用root用户来运行,容器内部用户的权限与外部用户相同,所以一定要确保容器执行者的权限和挂载数据卷对应

    扩展干货...(后续会继续补充)

    1、为什么docker输出的文件权限为 root?

    Docker容器运行的时候,如果没有指定user,容器内部默认以root用户运行

    2、怎么确定运行的用户为root?

    可以通过容器里的执行用户的id是0,输出文件的权限也是0。

    当docker容器运行在宿主机上的时候,仍然只有一个内核。容器共享宿主机的内核,所以所有的uid和gid都受同一个内核来控制。
    比如,当一个进程尝试去写文件,内核会检查创建这个进程的的user的uid和gid,来决定这个进程是否有权限修改这个文件。

    # 怎么查看用户的UID和GID?
    (1)id 用户名
    (2)cat /etc/passwd | grep 用户名
    # root:x:0:0:root:/root:/bin/bash
    # 两个bai0就是uid和gid

    3、为什么容器里的用户名不一定和宿主内核一样呢?

    比如,test 容器的用户叫做 test, 而本机没有 test 这个用户。这是因为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

    解决方案

    方案一 : 关闭SELinux

    • 临时关闭(不用重启机器)SELinux
    # 执行命令
    setenforce 0 
    • 修改配置文件需要重启机器(或者使用source使其生效,没有亲测,不确定是否有效)
    # 修改/etc/selinux/config 文件
    将SELINUX=enforcing改为SELINUX=disabled

    方案二:指定user

    • 使用run的时候指定
    # 通过volume挂载的方式,指定运行user为1001, 启动容器 test:
    docker run -d --name test -p 8080:8080 -u 1001:1001 -v $(pwd):/tmp test
    # docker run -u 可以指定宿主机运行docker命令的用户, -u指定的uid就是docker实际运行的进程拥有者
    • 亦可以在dockerfile的时候指定
    RUN useradd -r -u 1001 -g test test
    USER test
    # -g:指定用户所属的群组。值可以使组名也可以是GID。用户组必须已经存在的,期默认值为100,即users。
    # -u:指定用户ID号。该值在系统中必须是唯一的。0~499默认是保留给系统用户账号使用的,所以该值必须大于499。
    # -r:建立系统账号。
    # USER指令用于指定容器执行程序的用户身份,默认是 root用户。
  • 相关阅读:
    【转】三层架构,MVC, ASP.net MVC的区别
    code-Behind
    从输入 URL 到页面加载完成的过程中都发生了什么事情?
    javascript杂谈
    网页设计中透明效果的使用技巧
    phpstorm+Xdebug断点调试PHP
    MySql IFNULL 联表查询出来的null 如何赋值
    php读取目录下的文件
    CI框架程序--本地调试之后部署新浪SAE
    各个手机APP客户端内置浏览器useragent
  • 原文地址:https://www.cnblogs.com/yfacesclub/p/14083299.html
Copyright © 2020-2023  润新知