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

本文会讲解在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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容