美文网首页
Docker非root用户修改/etc/hosts文件

Docker非root用户修改/etc/hosts文件

作者: 莹宝与梨梦 | 来源:发表于2019-05-07 22:00 被阅读0次

    本文会讲解在Docker容器环境下,非root用户如何编辑修改/etc/hosts文件。

    1、背景和需求描述

    环境:Docker
    运行用户:非root用户,如普通用户1001
    需求:应用运行在容器内,需要在容器内/etc/hosts文件中添加例如hbase主机名称的解析。
    

    2、解决思路

    以下的篇幅会描述针对这个需求,对应尝试的方案和思路,当然最终也解决了这个问题,文中会附上相应的实践,有兴趣的读者可以跟着命令操作一遍。

    2.1 思路1(失败)

    我们都知道,/etc/hosts文件对于普通用户一般只有 只读权限,既然非root用户需要编辑并修改/etc/hosts文件,那么在镜像构建过程中,将/etc/hosts文件的权限chmod为777或者是666,是否能实现这个需求呢?我们可以来验证下。

    2.1.1 Dockerfile准备

    [root@hbs image]# cat Dockerfile 
    FROM docker.io/nginx:latest
    USER root
    RUN useradd act -u 1001 -g root -p 1001 && \
            chmod 777 /etc/hosts
    USER act
    

    2.1.2 镜像构建和运行

    [root@hbs image]# docker build -t docker.io/nginx:v1 .
    [root@hbs image]# docker run -it --rm docker.io/nginx:v1 /bin/bash
    act@2488c623e6fe:/$ id
    uid=1001(act) gid=0(root) groups=0(root)
    act@2488c623e6fe:/$ cd /etc/
    act@2488c623e6fe:/etc$ ls -l | grep hosts
    -rw-r--r-- 1 root root     174 May  8 13:28 hosts
    act@2488c623e6fe:/etc$ echo "10.10.10.10 hbs.com" >> /etc/hosts
    bash: /etc/hosts: Permission denied
    

    从上面的运行过程中可以看出,虽然在镜像构建的时候中已经将/etc/hosts文件的权限chmod为777了,但实际以普通用户act启动容器时,发现/etc/hosts权限并没有改变,还是644,自然而然act用户也就无法编辑修改/etc/hosts文件了,这里我们就要思考一下了,为啥在镜像构建过程中修改/etc/hosts文件权限,运行时却不生效呢?
    其实这个问题,好心的网友已经有针对该问题做相应的解释了,原因就是:

    hosts文件并不是存放在镜像中的,/etc/hosts,/etc/resolv.conf和/etc/host这几个文件是存放在/var/lib/docker/containers/${container-id}目录下的,容器启动时是将这些文件挂载到容器内的,换句话说,在镜像构建过程中对/etc/hosts文件的修改并不会同步到容器内的,这点我们可以从容器内看出来,如下。
    
    act@2488c623e6fe:/etc$ df -h
    Filesystem      Size  Used Avail Use% Mounted on
    overlay          50G  5.2G   42G  11% /
    tmpfs           1.9G     0  1.9G   0% /dev
    tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
    /dev/vda1        50G  5.2G   42G  11% /etc/hosts
    shm              64M     0   64M   0% /dev/shm
    tmpfs           1.9G     0  1.9G   0% /proc/acpi
    tmpfs           1.9G     0  1.9G   0% /proc/scsi
    tmpfs           1.9G     0  1.9G   0% /sys/firmware
    
    我们可以看到,/etc/hosts文件确实是以挂载的方式mount到容器内部的。
    

    2.2 思路2(成功,算是比较简便的方式)

    无论是原生的docker命令,或者是以YAML文件方式(kubectl)进行部署,都支持在运行容器时,动态往/etc/hosts文件中设置其他的域名解析。

    2.2.1 docker原生命令

    启动容器时在docker run命令后加上如下命令:--add-host ${host.name}:${host.ip},我们可以来验证下:

    [root@hbs image]# docker run --add-host hbs.com:10.10.10.10 -d docker.io/nginx:v1
    e8d77f865c87b133ee60eaa41666422426fb96fe4e807e2b8bec81941fb5174b
    [root@hbs image]# cat /var/lib/docker/containers/e8d77f865c87b133ee60eaa41666422426fb96fe4e807e2b8bec81941fb5174b/hosts
    127.0.0.1       localhost
    ::1     localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    10.10.10.10     hbs.com
    172.17.0.3      e8d77f865c87
    

    从上面的运行结果来看,非root用户下,通过在运行时添加--add-host命令确实能满足要求。

    2.2.2 YAML文件方式部署

    在k8s容器云环境下,以YAML文件的方式部署应用,也能满足这种需求,但对k8s有版本要求,从1.7版本之后,k8s支持了HostAliases特性实现向Pod的/etc/hosts文件中添加条目,我们可以来验证下:

    [root@hbs ~]# kubectl version
    Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
    Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:02:58Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
    
    [root@hbs appdata]# kubectl get deployment nonexistent-goose-hbs-helm -o yaml -n helm-test > helm-test.yaml
    [root@hbs appdata]# vim helm-test.yaml
    
        spec:
          hostAliases:
          - ip: "1.2.3.4"
            hostnames:
            - "hbs.com"
          containers:
          - image: docker.io/nginx:latest
    
    [root@hbs appdata]# kubectl apply -f helm-test.yaml -n helm-test
    [root@hbs appdata]# kubectl exec nonexistent-goose-hbs-helm-7d846fffb5-zdsln cat /etc/hosts -n helm-test
    # Kubernetes-managed hosts file.
    127.0.0.1       localhost
    ::1     localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    fe00::0 ip6-mcastprefix
    fe00::1 ip6-allnodes
    fe00::2 ip6-allrouters
    10.244.0.12     nonexistent-goose-hbs-helm-7d846fffb5-zdsln
    
    # Entries added by HostAliases.
    1.2.3.4 hbs.com
    

    从上面 的运行结果来看,使用hostAliases属性也同样能满足我们的要求,但还有一个特例,就是如果Pod启用hostNetwork,将不能使用这个特性,因为kubelet只管理非hostNetwork类型的Pod的hosts文件。

    2.3 思路3(成功,sudo修改镜像)

    这种是本文所采用的方式,因为本文的具体场景需求是:通过一个批次调度平台来启动一个Pod,Pod的YAML文件生成是由批次调度平台来决定的,经调研批次调度平台无法支持通过hostAliases属性来动态生成/etc/hosts,所以出发点还是在镜像这一块。
    既然在镜像构建过程中chmod /etc/hosts文件不生效,详情可看2.1 思路1,那么换另外一种思路,就是在容器启动后,动态chmod /etc/hosts权限,然后进行编辑,这种思路就转换为另外一个问题,就是普通用户是无法执行chmod命令,经调研,sudo能让普通用户切换为root用户然后有权限执行指定的命令,具体实践可看以下:

    [root@hbs image]# cat Dockerfile
    FROM docker.io/dustise/yum.centos7:latest
    USER root
    RUN useradd act -u 1001 -g root && \
            yum install -y sudo && \
            echo "act ALL=(root) NOPASSWD: /usr/bin/chmod" >>  /etc/supoers
    USER act
    
    其中主要关注**echo "act ALL=(root) NOPASSWD: /usr/bin/chmod" >>  /etc/supoers**这一句命令,意思是普通用户act在执行sudo chmod这句命令时能短暂切换为root用户并且执行chmod操作,NOPASSWD命令是切换用户无需输入密码。
    
    [root@hbs image]# docker build -t docker.io/yum.centos7:v3 . --no-cache
    [root@hbs image]# docker run -it --rm docker.io/yum.centos7:v3 /bin/bash
    [act@9c9f5c15abc8 /]$ id
    uid=1001(act) gid=0(root) groups=0(root)
    [act@9c9f5c15abc8 /]$ sudo chmod 777 /etc/hosts
    [act@9c9f5c15abc8 /]$ echo "11.22.33.44 hbs.com" >> /etc/hosts
    [act@9c9f5c15abc8 /]$ cat /etc/hosts
    127.0.0.1       localhost
    ::1     localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    172.17.0.3      9c9f5c15abc8
    11.22.33.44 hbs.com
    

    从上面的运行结果来看,执行sudo命令时,系统会去/etc/supoers文件中查找是否支持当前用户进行相应的操作,由于在镜像构建过程已经将act ALL=(root) NOPASSWD: /usr/bin/chmod写入到/etc/supoers文件中了,所以普通用户执行sudo chmod 777 /etc/hosts这句命令时能切换到root用户,然后执行chmod操作,/etc/hosts文件的权限一修改,自然而然就可以进行编辑追加了。

    3、参考资料

    Docker修改hosts
    linux /etc/supoers文件详解
    Adding entries to Pod /etc/hosts with HostAliases

    相关文章

      网友评论

          本文标题:Docker非root用户修改/etc/hosts文件

          本文链接:https://www.haomeiwen.com/subject/mzndoqtx.html