本文会讲解在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. CPU性能测试基准(Dhrystone)学习

    简介 Dhrystone是测量处理器运算能力的最常见基准程序之一,常用于处理器的整型运算性能的测量.程序是用C语言编写的,因此C编译器的编译效率对测试结果也有很大影响. Dhrystone是由Rein ...

  2. 什么是 js 事件循环 event loop

    知识储备 : js 的执行 机制 js 的底层执行机制 : 对于 js 代码 分为了同步 和 异步 代码 ,异步代码 较少比如:setInterval setTimeout 等(不会超过10 个) 其 ...

  3. vue3自动导入 api ,不需要多次导入 api 了

    安装插件   npm i -D unplugin-auto-import 配置 vite.config.js export default defineConfig({ plugins: [ vue( ...

  4. 探索 Kubernetes 持久化存储之 Longhorn 初窥门径

    作者:运维有术星主 在 Kubernetes 生态系统中,持久化存储扮演着至关重要的角色,它是支撑业务应用稳定运行的基石.对于那些选择自建 Kubernetes 集群的运维架构师而言,选择合适的后端持 ...

  5. LDAP和SSO

    什么是LDAP(Lightweight Directory Access Protocol)?很多公司会使用各种开源平台(例如: gitlab. Jenkins. chat 等等),维护这些账号是一件 ...

  6. C#_自定义简单ORM

    一,基本思路:利用C#的标签和反射功能实现自定义轻量级ORM 标签Attribute附着在实体属性或实体类名上,这样可以取到实体对应的表名,属性对应的表字段名,数据类型,是否主键,字段注释等基本信息 ...

  7. 基于CTFshow的文件上传二次渲染绕过与CTF实战

    1. 二次渲染简介 二次渲染指的是上传的文件(如图片),为了显示的更加规范(尺寸.像素),网站会对文件进行二次处理,经过解码或转换可能导致其中的恶意代码失效.例如,后门程序在图像渲染过程中可能被清除或 ...

  8. 开源 - Ideal库 - 常用枚举扩展方法(一)

    今天和大家享一些关于枚举操作相关的常用扩展方法. 我们平时用的比较多的是正常枚举,同时还有加[Flags]特性的位标志枚举,因此以下所有扩展方法同时适用正常枚举以及位标志枚举. 我们首先定义两种枚举用 ...

  9. 六、FreeRTOS学习笔记-任务挂起和恢复

    任务的挂起与恢复的API函数介绍 API函数 描述 vTaskSuspend() 挂起任务 vTaskResume() 恢复被挂起的任务 xTaskResumeFromISR() 在中断中恢复被挂起的 ...

  10. C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)

    前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...