欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Docker基础:指定USER的容器中获得root用户的方法

程序员文章站 2024-03-14 17:40:34
...

在很多官方镜像中,为了安全,都会将用户进行限定,而不是缺省使用root。比如Jenkins的官方镜像,docker exec进去之后的用户就是jenkins,但是偶尔有需要在运行态以root权限修改当前容器设置的需求时,可使用-u选项来解决这个问题。

问题描述

以Jenkins的alpine的lts容器为例,进行说明。在官方Alpine的Jenkins镜像中安装NodeJS插件,然后创建一个Free Style 的Job,在此Job中执行node -v和npm -v执行版本的确认,发现无法正常动作,日志输出信息如下:

Started by user admin
Running as SYSTEM
Building in workspace /var/jenkins_home/workspace/nodejs-freestyle-job
Unpacking https://nodejs.org/dist/v10.15.3/node-v10.15.3-linux-x64.tar.gz to /var/jenkins_home/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs10.15.3 on Jenkins
[nodejs-freestyle-job] $ /bin/sh -xe /tmp/jenkins5559044380616609516.sh
+ npm -v
env: ‘node’: No such file or directory
Build step 'Execute shell' marked build as failure
Finished: FAILURE

详细的问题现象和原因说明请参看:
*

问题对应方法

想定的对应方法:
从其他地方获取一个nodejs的二进制包,然后展开在/usr/local下

问题:
在/usr/local下当前用户没有创建目录的权限。操作日志如下所示

liumiaocn:~ liumiao$ docker ps |grep jenkins |grep alpine
6535aece8684        jenkins/jenkins:lts-alpine   "/sbin/tini -- /usr/…"   5 hours ago         Up 5 hours          0.0.0.0:8080->8080/tcp, 0.0.0.0:60000->50000/tcp    mystifying_spence
liumiaocn:~ liumiao$ docker exec -it mystifying_spence sh
/ $ id
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
/ $ mkdir -p /usr/local/node
mkdir: cannot create directory ‘/usr/local/node’: Permission denied
/ $ ls -ld /usr/local
drwxr-xr-x 1 root root 4096 Oct 18 07:21 /usr/local
/ $

原因:
jenkins的官方镜像通过USER指令限定了缺省用户,可以防止root权限的滥用。但是这同样带来了问题,因为在容器之中,su和sudo均无法直接使用。

注:解决方式有多种,这里只是为了介绍这种类似情况下如何获得root权限并进行操作

对应方法

对应方法:
docker exec -it时通过-u参数指定root作为操作用户即可。操作示例日志如下所示

步骤1: 修改nodejs插件配置

按照如下方式设定nodejs的路径
Docker基础:指定USER的容器中获得root用户的方法

步骤2: 以root身份进入到Jenkins镜像中

liumiaocn:~ liumiao$ docker exec -it -u root mystifying_spence sh
/ # id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
/ # 

可以看到只需要指定-u的参数,即可获得了root的权限进行操作。

步骤3: 创建目录并解压nodejs二进制包

将预先获取的Alpine版的nodejs二进制文件放置到上述设定的目录下

liumiaocn:~ liumiao$ docker cp nodejs.10.15.3.tar mystifying_spence:/tmp
liumiaocn:~ liumiao$ docker exec -it -u root mystifying_spence sh
/ # id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
/ # ls -l /tmp/nodejs.10.15.3.tar 
-rw-r--r-- 1 501 dialout 62127616 Oct 18 01:07 /tmp/nodejs.10.15.3.tar
/ # 

这里有另外一个有趣的情况,注意上述user的id是501,这个userid从哪里来的呢?宿主机器的当前用户我们来确认一下

liumiaocn:~ liumiao$ id
uid=501(liumiao) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),701(com.apple.sharepoint.group.1),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh)
liumiaocn:~ liumiao$

因为容器中没有id为501的用户,所以才导致无法显示用户名称。

/ # grep 501 /etc/passwd
/ # grep 1000 /etc/passwd
jenkins:x:1000:1000:Linux User,,,:/var/jenkins_home:/bin/bash
/ # 

但是由于我们有root的用户权限,这些都不是问题。

/ # mkdir -p /usr/local/node/10.15.3
/ # cd /usr/local/node/10.15.3/
/usr/local/node/10.15.3 # tar xf /tmp/nodejs.10.15.3.tar 
/usr/local/node/10.15.3 # ls
bin  include  lib  share
/usr/local/node/10.15.3 # ./bin/node -v
v10.15.3
/usr/local/node/10.15.3 # ldd bin/node 
	/lib/ld-musl-x86_64.so.1 (0x7f22f84b3000)
	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f22f6409000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f22f63f5000)
	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f22f84b3000)
/usr/local/node/10.15.3 # 

而通过Jenkins再次执行Job,也获取的npm和node的正常版本信息。
Docker基础:指定USER的容器中获得root用户的方法

总结

可以看到使用-u root即可获得root的权限进行操作,但是在实际应用时只能作为权益之举,虽然很多时候权益之举会变成例行操作。