场景

笔者在宿主机上的用户,是一个具有“宿主机上sudo权限”的非root用户。现在在宿主机有资源文件夹CPP,里边有各种库。但是有的库需要glibc 2.31才能用。然而,宿主机ubuntu 16.04的glibc版本为2.23,且无法升级(升级了可能16.04的系统就打不开了,这系统太老)。所以,笔者决定采用docker拉取一个ubuntu 20.04 的镜像,挂载宿主机CPP文件夹到容器的/mnt文件夹,从而完成开发工作。

问题

docker run创建容器时,在容器中默认使用root用户。或者可以通过–user参数指定非root用户。如果我们使用默认root用户创建容器,那么我们在容器中创建的所有文件,在宿主机看来也都是root创建的,非常难受,也不安全、不方便。然而,如果我们通过–user参数指定非root用户来创建容器,那我们从一开始就没有root权限,也就一直无法在容器中使用apt-get、sudo等命令,这是我们不能接受的。

我们希望:

  • 【以非root宿主机用户同名身份使用docker容器】docker容器中的用户能够与宿主机中用户拥有一样的用户名和用户组名,这样看起来比较统一。即,如果我们在宿主机中的用户名叫userAAA,那么在进入一个容器后,我们希望我们仍然还叫userAAA。
  • 【共享文件读写执行权限】在使用docker过程中所创建的文件,能够在宿主机和容器之间无缝切换。即,我们在宿主机中以userAAA身份创建的文件,挂载到容器中后,能够在容器中以userAAA的身份进行操作;而我们在容器中以userAAA的身份创建的问津,当我们回到宿主机后,仍然能以userAAA的身份进行操作。
  • 【能够在容器中执行sudo命令】容器中的userAA用户也拥有在容器中执行sudo命令的权限。

解决方案

不能上来就用非root用户身份去建立容器,因为那样的话,你在镜像里就是个普通用户,没法做初始化配置。所以需要先用root用户创建、运行容器,来配置环境;等配置好了之后logout退出,再用普通用户start这个容器即可。

操作步骤

记录一下操作流程。

建立并配置镜像

首先,在宿主机建立docker镜像,挂载宿主机的CPP文件夹到容器的mnt/CPP下。这时候,我们在容器中是root身份:

docker pull ubuntu:20.04
docker run -it -p 8005:8005 -v 宿主机绝对路径:/mnt/CPP ubuntu:20.04 /bin/bash

进去之后,在容器中以root身份安sudo和vim:

apt-get update
apt-get install sudo
apt-get install vim

查看宿主机用户id和用户组id

然后我们在容器中增加新用户。新增的这个用户,相当于“宿主机用户”在容器中的“影子”,二者应当具有相同的用户id和用户组id。只有这样,我们在容器中使用该用户所创建的文件,才能正确被宿主机识别。所以,我们需要暂离容器、回到宿主机,查看自己的用户id和用户组id。
这里,我们按ctrl+p+q暂离容器,回到宿主机中,确定自己的用户id和用户组id:

id -u            						这是用户id
id -g            						这是用户组id
docker ps        						查看容器名称
docker attach 容器名 					回到容器来

创建新用户并配置sudo权限

回到容器来后,我们开始创建用户组和新用户:

groupadd -g 用户组id	用户组名							这里的用户组id要与宿主机中的相同
adduser --uid 用户id -gid 用户组id 你的用户名			这里的用户id、用户名要与宿主机中的用户id、用户名相同。

然后要在容器中给非root用户添加sudo权限。打开sudoers配置文件:

vim /etc/sudoers

然后找到“# User privilege specification”这行。下边已经应该有一个root用户了,这代表root用户是可以使用sudo命令的。然后我们要把非root用户,也就是我们在宿主机上的用户,添加进去:```

#User privilege specification				这行应该是已经有了的
root  ALL=(ALL:ALL) ALL						这行也应该是已经有了的
用户名 ALL=(ALL:ALL) ALL						这行自己打上去

这时候可能你需要使用:wq!来强行修改该文件。你可以使用cat /etc/sudoers 命令查看你修改的结果。

给容器改名字

这里我们测试之前先给它改个名字。默认分配的名字是随机的,不利于后续使用。这里我们在宿主机中给容器改名。首先退出容器:

exit										退出容器

然后,我们使用docker ps -a命令查看刚才我们配置出来的这个容器,给它改一个合适的名字,重新启动这个容器:

docker ps -a  							NAMES那一列有名字,默认名字都是随机生成的
docker rename 旧容器名 新容器名  		改成一个更容易辨认的名字
docker restart 新容器名					启动该镜像

现在确认一下状况:我们以root建立了容器,安装了sudo和vim之后,创建了一个uid和gid与宿主机用户相同的非root账户,并为该用户添加了sudo权限。这就完成了我们的目标。

如何使用该容器

运行:docker restart 容器名
进入:docker exec -it -u 用户名 容器名 /bin/bash
暂离:容器内按Ctrl+P+Q
回到:docker exec -it -u 用户名 容器名 /bin/bash
关闭:docker stop 容器名
Logo

更多推荐