本文会讲解在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. 高通Perflock

    高通的Perflock是Qualcomm公司开发的一项技术,用于优化设备性能和功耗管理.Perflock是一种锁定机制,允许操作系统或应用程序在需要时对处理器的性能状态进行控制,从而确保在关键任务或高 ...

  2. Android Systrace 基础知识 -- Why 60 fps ?

    1.正文 今天来讲一下为何我们讲到流畅度,要首先说 60 帧. 我们先来理一下基本的概念: 60 fps 的意思是说,画面每秒更新 60 次 这 60 次更新,是要均匀更新的,不是说一会快,一会慢,那 ...

  3. 4.3.2 等比数列的前n项和公式

    \({\color{Red}{欢迎到学科网下载资料学习 }}\) [ [基础过关系列]高二数学同步精品讲义与分层练习(人教A版2019)] ( https://www.zxxk.com/docpack ...

  4. python:批量删除指定文件目录中多个文件

    #coding:utf-8# 任务需要,需要删除多余的文件,手动删除太麻烦,几行python搞定 import os from glob import glob path = r"/medi ...

  5. 封装一个Promise.all 的函数

    // 1. 准备三个异步函数 const promise1 = Promise.resolve('prom11ise1'); const promise2 = new Promise(function ...

  6. Android复习(六)核心组件—>Activity 简介、生命周期、状态变更

    1. 可以在activity上声明权限,来保证只在进入某个activity是否有某种权限 <manifest> <activity android:name="....&q ...

  7. Kubernetes 边缘节点抓不到监控指标?试试这个方法!

    KubeSphere v3.1.0 通过集成 KubeEdge,将节点和资源的管理延伸到了边缘,也是 KubeSphere 正式支持边缘计算的第一个版本. 笔者也第一时间搭建和试用了边缘节点相关的功能 ...

  8. 智子: Vue Vapor年底发布alpha版本,如果有资金支持

    前言 在最近的Vue Fes大会上,Vue Vapor的作者智子大佬宣布,如果能够得到资金支持,那么Vue Vapor年底就能发布alpha版本了. 关注公众号:[前端欧阳],给自己一个进阶vue的机 ...

  9. Go语言编写单元测试用例

    Go单元测试示例 example/ |--division.go |--division_test.go 为什么被测试文件和测试文件通常放到同一个文件夹下以及同一个声明包里 通常情况下,我们把被测试的 ...

  10. 在PyCharm中打包Python项目并将其运行到服务器上的方法

    在PyCharm中打包Python项目并将其运行到服务器上的方法 在PyCharm中打包Python项目并将其运行到服务器上的过程,可以分解为几个关键步骤:创建项目.设置项目依赖.打包项目.配置服务器 ...