因为本人平常喜欢以用户身份启动容器,这样宿主机上显示的任务进程便是我的名称而不是root用户,但是我偶尔也需要在容器中使用root权限,而直接以普通用户身份进去又没有管理员权限,所以就查了很多资料,才整理出一个简单的方法。
(在找的过程中有人是使用docker的namespace功能,我详细了解了之后感觉并不能满足我的需求,而且也比较麻烦)
更多docker使用小建议参见我的个人主页 https://www.yolomax.com/lab/skills/docker/
以非root用户启动容器
-
为什么要用非root用户启动容器
默认情况下,容器中的进程以 root 用户权限运行,并且这个 root 用户和宿主机中的 root 是同一个用户。所以大家直接启动容器,并在容器内部跑程序时,你在宿主机上用top等命令查看进程时,以及用nvidia-smi查看显卡使用时,显示的都是root用户在运行。
这样会带来几个问题。1. 你在容器中写的文件,保存的文件的拥有者并不是你,而是root用户,当你的容器被销毁后,你在宿主机上是没有权限对这些文件进行操作的。2. 对于其他用户来说,他人无法通过nvidia-smi查看显卡是谁在使用,因为通过进程ID查到的是root用户在跑程序。这不方便同学之间进行显卡利用的沟通,也不方便管理员监管。当部分进程有问题时,管理员不知道找谁。
-
怎么以非root用户启动容器。
docker run --user $(id -u ${USER}):$(id -g ${USER}) <其他参数>
通过
--user $(id -u ${USER}):$(id -g ${USER})
的参数可以指定以当前宿主机用户的身份启动容器。–-user
是用来指定docker容器中用户的id的,$(id -u ${USER}):$(id -g ${USER})
是自动解析id命令返回的uid和组id,这样就不用自己去查询id了。所以相比于之间大家使用docker,唯一的改变就是在启动容器的时候加上
--user $(id -u ${USER}):$(id -g ${USER})
这一段话就可以了。 -
如何以非root身份启动容器,但是能在容器中获得root权限。
要实现这个功能,需要两步,一步是修改dockerfile文件,另一步是在启动容器时添加一段命令。
-
修改dockerfile
修改的目标是安装sudo包和给某个你所在的组添加管理员权限。这样你就能在容器中使用sudo获得管理员权限。在介绍完修改命令后我会给出一个完整的dockerfile帮助大家理解。
1.1 第一段命令
apt-get update && apt-get install sudo
可见这一段话的意思是安装sudo命令的,以方便你在获得管理员权限后能通过sudo操作。当然,如果你的当前镜像已经安装了sudo命令,可以不执行这一段话。可以通过在基础镜像开启的容器中执行sudo操作来试试自否有安装sudo命令。
1.2. 第二段命令
cp /etc/sudoers /etc/sudoers.new && echo "%docker ALL=(ALL:ALL) ALL" >> /etc/sudoers.new && visudo -c -f /etc/sudoers.new && cp /etc/sudoers.new /etc/sudoers && rm /etc/sudoers.new
/etc/sudoers这个文件是管理sudo权限的,从名字就可以看出来。这一段命令的意思是给docker组内的所有成员添加管理员权限,如果你不是在docker组里,可以换成别的你在的组,将组名替换第二行的docker这个单词就行了。
加上这两段话后就可以构建镜像并启动容器了。
dockerfile的例子 : https://github.com/yolomax/docker/blob/pytorch1.7.0/pytorch
-
启动容器时添加的命令
docker run --user $(id -u ${USER}):$(id -g ${USER}) -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -v /etc/shadow:/etc/shadow:ro <其他参数>
这一段参数的意思是将宿主机上的用户组以及密码以只读的形式全部挂在到容器中。
为什么要做这个映射呢。在第一部修改dockerfile时,我们已经给容器中的某个用户组添加了管理员权限(比如我上面命令中的docker组)。但是直接启动容器时是没有组和用户的信息的,所以你要把宿主机上的组合用户的信息映射到容器中。
-
下面我讲一个在容器中以管理员权限开启ssh服务的例子
这样我就可以在容器中开启ssh服务,可以远程登录此容器,也可让本机的pycharm通过ssh获得容器中的python解释器。
在容器中我可以执行
sudo /etc/init.d/ssh start
输完命令后系统会让你输入密码,因为我们已经将宿主机上的用户和密码都映射进来了,所以这里输入的密码就是你宿主机上的密码
-