本文会讲解在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文件的更多相关文章

  1. docker 非root用户修改mount到容器的文件出现“Operation not permitted

    使用环境centos7 x86-64 内核版本4.19.9 docker使用非root用户启动,daemon.json配置文件内容如下: # cat daemon.json { "usern ...

  2. Docker非root用户使用

    Docker 用户管理 安装Docker后docker相关命令都需要加上sudo才能执行,这里为特定用户添加下权限 Docker群组 不过一般安好docker后该群组已创建 sudo groupadd ...

  3. linux centos7 非root用户安装源码版docker

    注意:非root用户必须要有sudo权限 一.安装前的准备 1.查看当前主机是否有docker组 若没有输出结果则新建 再次查看,发现已经有了docker组 2.新增拥有sudo权限的用户(若知道ro ...

  4. 二进制方式安装docker(非root用户启动docker)

    二进制方式安装docker(非root用户启动docker) 一.下载安装包: 地址:https://download.docker.com/linux/static/stable/x86_64/ 这 ...

  5. Docker 为非root用户授权

    Docker 为非root用户授权: 当运行docker pull busybox时候,会提示sky用户无法调用docker. 那么应该把sky用户加入docker用户组,不过在添加的时候,又提示了如 ...

  6. Linux 下非root用户使用docker

    Linux 下非root用户使用docker 通常我们使用linux系统的时候,最好是不要直接使用root账号,但是使用Docker的时候,默认又是不能使用非root用户的,关于原因,官方说法如下: ...

  7. 【出错记录】Tomcat非root用户启动无法拥有权限读写文件

    简单记录下,如有必要,将深入补充: 一.非root用户运行Tomcat及原因 由于项目中,为了安全需要,Tomcat将禁止以root形式启动,原因很简单,举个例子,一旦有人恶意将jsp文件透过某个别的 ...

  8. EasyHLS直播在Linux非root用户运行时出现无法写文件的问题解决mkdir 0777

    今天在Github上收到一个用户反馈的EasyHLS在linux上非root用户调用时,无法写目录的问题:https://github.com/EasyDarwin/EasyHLS/issues/3, ...

  9. centos6.5下修改系统的roo用户/非root用户的密码

    1.修改系统root用户的密码 [........~]# passwd然后输入新密码,若提示密码太简单,无需理会,直接敲回车: 然后再次输入新密码,即可修改成功. 2.修改系统非root用户的密码:e ...

  10. 非root用户搭建hadoop伪分布式

    0.安装软件列表 jdk-7u25-linux-x64.tar.gz hadoop-2.5.0.tar.gz hadoop-native-64-2.5.0.tar   1.准备Linux环境(root ...

随机推荐

  1. android启动时间测试

    需要对比基线测试的情况: Kernel log: adb shell dmesg Event log: adb shell logcat –b events Logcat log: adb shell ...

  2. 05 Transformer 中的前馈神经网络(FFN)的实现

    2:20:理论链接 博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链 ...

  3. .NET 内存管理两种有效的资源释放方式

    前言 嗨,大家好!今天我们要聊一聊 .NET 中的内存管理.你知道吗?虽然 .NET 有一个很好的垃圾回收系统来自动清理不再使用的对象,但在某些情况下,我们还需要自己动手来释放一些特殊的资源,比如打开 ...

  4. 牛逼!5K star! 推荐一款集监控和埋点于一体的前端性能监控工具!开源、简单易用、功能强大!

    在互联网的快速发展下,网站已成为企业和个人展示信息.提供服务的重要平台.然而,随之而来的网站性能问题也日益凸显,如加载速度慢.频繁出错.服务器故障.数据异常.网络攻击等.如何确保用户能够快速稳定地访问 ...

  5. Java 当中使用 “google.zxing ”开源项目 和 “github 的 qrcode-plugin” 开源项目 生成二维码

    Java 当中使用 "google.zxing "开源项目 和 "github 的 qrcode-plugin" 开源项目 生成二维码 @ 目录 Java 当中 ...

  6. DRF-Parser解析器组件源码分析和应用

    1. 解析器源码分析 注意:以下源码为了方便理解已进行简化,只保留了解析器相关的代码 # 视图函数: class MyView(APIView): def post(self, request): p ...

  7. Go语言单元测试的执行

    Go 语言推荐测试文件和源代码文件放在同一目录下,测试文件以 _test.go 结尾.比如,当前 package 有 calc.go 一个文件,我们想测试 calc.go 中的 Add 和 Mul 函 ...

  8. 部署个SSH蜜罐玩玩,又能增强安全性,又能当电子蛐蛐

    前言 最近有个旧服务器的 SSL 证书过期了,每次都申请 SSL 证书太麻烦了,我直接把 swag 方案部署上去. 然后发现这个服务器在安全方面有所疏忽,所以又加固了一下,SSH 部分我想起来之前用过 ...

  9. Windows系统DOS命令详解

    一. DOS 的历史 DOS(Disk Operating System),磁盘操作系统 1980 年,西雅图程序员蒂姆-帕特森,86-DOS 1981 年由微软公司购买并改进,更名为 MS-DOS ...

  10. python之执行shell命令

    python 执行shell命令,且执行完后将shell端的输出返回 subprocess import subprocess # 要执行的命令 command = "ls -lrt&quo ...