Docker基础:指定USER的容器中获得root用户的方法
在很多官方镜像中,为了安全,都会将用户进行限定,而不是缺省使用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的路径
步骤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的正常版本信息。
总结
可以看到使用-u root即可获得root的权限进行操作,但是在实际应用时只能作为权益之举,虽然很多时候权益之举会变成例行操作。