突然想起这个问题。之所以问这个问题,是因为我最近使用 jupyter 的官方镜像,但是发现登陆的用户不是 root,缺少一些权限。
--user
参数这一种方法吗?) 1
likuku 2018-11-21 21:24:23 +08:00
你这是把 docker 当虚拟机来用了...
|
2
CivAx 2018-11-21 21:30:14 +08:00
你这是把 docker 当虚拟机来用了...
|
3
zmj1316 2018-11-21 21:41:41 +08:00
我这里进去就是 root 啊,docker 默认就是 root,其他用户才需要自己建
LS 别笑话,我还真拿 docker 当虚拟机使了🤣,每个容器单独开 ssh 映射接口出去,然后挂外面的文件夹。 因为一台机器需要配各种环境给好多人用,每个人都要 root 权限装东西,折腾坏了还要重新配环境,除了 docker 没啥好用的了。 |
4
CivAx 2018-11-21 21:47:52 +08:00
1、docker history $imageID
可以用来观察在你 docker pull 或者 docker run xxx 的时候,docker 自动帮你配置的镜像分别执行过什么命令。 2、除非你用的自定义镜像;官方所有镜像都是(大都是)基于 Debian 8 来构建,并且使用 ROOT 账号执行命令, --user 的作用不是指定“这个容器内的默认用户是谁”,而是决定“由宿主机的谁来运行这个容器”,详见 Linux nameSpace 说明文档。如果一定要指定镜像的运行时用户,可以用 Dockerfile 中的 USER 参数指定,任何写在 USER 以下的命令都会被以 $USER 来执行 3、docker -it exec root $containerName bash 翻译: docker -参数(启用交互式 分配伪终端) exec 以 root 用户身份 $容器名 使用 bash 作为 session (你开心可以用 sh ) |
5
rizon OP @CivAx #4
你说的 --user 表示的是宿主机的用户?可是我使用`docker exec --user jovyan -it datascience_jupyter_lab bash`这个命令登陆进去就是 jovyan 这个用户,但是这个用户宿主机里是没有的。 所以这里匹配的还是容器里的用户吧 |
7
stebest 2018-11-21 23:04:20 +08:00
这些都是 linux 的基本操作,,,和 docker 没啥关系,在 Linux 怎么创建用户怎么切换用户,在这里就怎么弄
|
8
gam2046 2018-11-22 08:34:30 +08:00
@CivAx 求大佬科普下。
我感觉 Docker 内分帐号意义并不是很大,因为 docker 本身被设计成一个容器只做一件事(虽然有人会在单容器内启动多个业务)。 那么在一个容器,只有一个工作的情况下,再划分多个帐号的意义是什么呢?退一步说,即使容器内业务存在漏洞,被人渗透,取得 webshell 或其他同等性质的权限。容器内的 root 并没有什么特别。 尽管如此,我发现有些镜像,例如 php、Tomcat 一类的,依旧会采用多用户的形式,例如会创建一个 www-data 的用户。而非采用默认的 root。所以,我觉得这其中应该有我没想到的原因吧? |
9
kios 2018-11-22 08:48:26 +08:00
我觉得你对 docker 的理解错了
|
10
grantonzhuang 2018-11-22 08:59:30 +08:00 via Android
@gam2046 我也有相同的疑问
|
11
shylockhg 2018-11-22 09:00:27 +08:00
docker container 就是活在妄想里的宿主机进程。。。
|
14
Hzzone 2018-11-22 09:49:04 +08:00
|
15
passerbytiny 2018-11-22 10:12:54 +08:00
@zmj1316 如果你只把 /opt 目录挂载成卷,那么创建用户、yum/apt-get 安装程序等等操作,容器都是干不了的,必须重建镜像;如果你把 /etc、/usr/local、/var 都挂载成了卷,那这容器就是个云主机,还需要脱裤子放屁地映射端口:那么用 docker 当虚拟机到底有啥好处。不会是不挂载数据卷,出问题的时候直接销毁并重建容器吧,相当于“快速重新安装系统”。
|
16
CivAx 2018-11-22 10:14:01 +08:00
@gam2046
第一段: 我就被要求过一个 Docker 起一堆服务打包成一个“系统”来进行快速部署,然后在 V 友的帮助下劝说了他放弃了这个念头(可以翻翻我的发帖纪录,我觉得那个帖子仅为其中的评论也都值得收藏)。 第二段: 实际上是有“特别”的。 除了极其严重的“ Docker 逃逸”等漏洞,还有一个十分低级但很常见的错误会导致以 root 权限运行的容器会另宿主机暴露在风险之中。 由于 nameSpace 的关系,如果你在 docker run 的时候--user 指定为 root,那么这个容器(实际上恰当的叫法是进程)则活在 root 的 nameSpace 里,也就是俗称的“具有 root 权限”。如果你还不幸地挂载了高危目录,譬如 -v /:/host 或者 -v /etc:/etc,那么一旦因为某些软件的漏洞,攻击者攻破进入到容器中,他直接 chroot 就直接有可以破坏宿主机的能力。 第三段: “ docker run -it debian ” “ cat /etc/passwd ” ---- “ docker run -it tomcat ” “ cat /etc/passwd ” “ cat /etc/issue ” |
17
julyclyde 2018-11-22 10:18:48 +08:00
我还以为没人批判把容器当虚拟机用呢,原来还是有懂行的人的
|
18
Beebird 2018-11-22 10:26:30 +08:00
@rizon 出于安全考虑,越来越多的 docker image 中的 User 不再是 root 了,如果你一定要以 root 身份登录到 docker container 中,可以试试 docker exec --privileged -u root -it <container id> sh
|
19
zmj1316 2018-11-22 10:33:42 +08:00
@passerbytiny 我只挂外面用户自己的数据卷,方便直接跑代码和模型,挂其他的我还怎么配不同的环境啊......非要建用户直接在 Dockerfile 里面建就行了啊。容器被玩坏了就直接从 image 重新开一个出来,数据卷一直在的。
主要目的一个是方便配环境,网上去下就行了,还有因为用户是小白,经常会玩坏系统。。。。。。 我的情况是,一个实际用户会需要开多个不同环境的容器,挂的是同一个数据卷,一个容器只有一个实际用户使用的。。。 |
20
ipwx 2018-11-22 10:41:13 +08:00
@zmj1316 我大概理解你的场景,但是我觉得你的管理方法有问题。
我建议你开放 docker 权限给你们组里面其他人,每个人专用自己的环境。好多人共用一个 Docker 环境,这和原来的直接裸机装环境,有什么差别呢? 什么,你说裸机装机太麻烦?我这边都是用 Ansible 装裸机环境的。被搞坏了很快就能回复。当然,在此之前,我会对一切要求我用 root 装环境的组员说不,所以也就没那么多可能的搞坏的情况了。 如果不下方 Docker 容器的权限给组员,有组员要 Python 2,有组员要 Python 3,有组员要特殊的系统包才能运行 pip,都来找你处理吗? |
22
zmj1316 2018-11-22 10:48:38 +08:00
@ipwx
1. 我这里容器专人专用,谁要用某个环境,我就给他从对应的 image 开一个容器和配套的端口,把他的数据卷挂进去,没有共用的说法。 2. 这些都是一次性的要求,每次有新的环境要求出来,我都单独配好 image,下次谁再要的我就直接从现有的开容器出去了。像 py 版本这样简单的需求,让他自己去容器里面装都没事,反正容器就他自己用,root 自己折腾去😄 |
23
raysonx 2018-11-22 10:50:12 +08:00
@zmj1316 @rizon 又见 X-Y 问题( https://coolshell.cn/articles/10804.html )。。。
用户需要的不是容器本身,而是为了解决某一实际问题,容器只是你为了解决某问题而设想的一种手段。你应该直接说为了解决什么问题,而不是隐藏要解决的问题,自己提出一种方案,然后询问要关于这种方案的问题。 |
24
raysonx 2018-11-22 10:55:10 +08:00 1
回到正题:
> docker 镜像默认是不是没有密码? 没有。容器不是虚拟机,只是内核提供的一种资源隔离手段。Docker daemon 本身是以 root 用户运行的,在创建新进程时直接用 setuid 就可以切换为指定的用户。 > 那么一些镜像如果用户不是 root 用户该怎么切换用户呢?(只有 使用--user 参数这一种方法吗?) 对,只有这一种方法。实际用户是由容器启动时决定的而不是镜像构建时决定的,镜像中只是指定了--user 参数的默认值。 > 如果我修改了用户的密码,那么 docker 的 exec 命令还可以直接进入到 bash 吗?如果可以想问一下这个 exec 命令是什么原理?为什么不用关心用户权限。 假设无效,见问题 1 的回答。 |
25
zmj1316 2018-11-22 10:56:15 +08:00
@raysonx 实践出真知,又不是我设想的,我用了以后的确摆脱了大量的 SA 工作啊。
用户要的就是个能 root 的虚拟机,可是显卡虚拟化太蛋疼了,还要帮用户配环境太蛋疼了,有那个找人问的时间我早已经把问题解决掉了。 |
27
passerbytiny 2018-11-22 11:08:05 +08:00
@zmj1316 结合你楼下的回复,大致推测你的管理方式:来一个人或任务就给一个容器,搞坏了或者不想用了,容器直接销毁;每个人有一个专门的数据卷。
首先要说明一点,你这种环境,数据卷只起到了外置可共享磁盘的作用,或者就叫做:可挂载的网盘。 你这种方式正好应了我原来的推测: [不会是不挂载数据卷,出问题的时候直接销毁并重建容器吧,相当于“快速重新安装系统”。] 你这种工作,不用 docker,换成 hyper-v、vmware、virtualbox 都能做,而且制作镜像、挂载和管理共享盘、配置网络等等更方便。 |
28
rizon OP |
29
zmj1316 2018-11-22 11:52:11 +08:00 via Android
@passerbytiny 因为这几个虚拟机没有现成的镜像,而 docker 有丰富的 dockerfile 资源,拿来就用,我这人懒🤣。
并且这几个要搞 gpu 虚拟化什么的,配起来很麻烦,不像 nvidia docker 基本无缝。 |
30
raysonx 2018-11-22 13:03:38 +08:00 via Android
@rizon 你的理解是不对的。Docker 默认不启用 user namespace,容器内的用户和主机的用户实际上是相同的。你看到的只是用户名不同,用户名只是一个显示问,那是虚的,实际的 uid 是相同的。假如你在 docker 里以 root 用户运行,他就是真正的 root 用户,只不过 docker 默认 drop 了一些 privilege。假如你挂载一个卷,里面只允许 root 用户读写,则容器里的 root 用户也是可以读写的。
su 要求密码只是 su 自己的逻辑。在 host 上运行 docker exec --user 不需要任何密码。 |
31
raysonx 2018-11-22 13:20:34 +08:00 via Android 1
继续补充:
su 和 sudo 这种程序是带有 setuid 属性的程序,普通用户执行这个程序会被提权到 root。验证密码只是 su 和 sudo 的内部逻辑。 总之,我想表达的意思是,docker run 或者 docker exec 不需要密码的本质原因是,docker daemon 是以 root 用户运行的,启动 container 的过程就是创建子进程的过程,子进程一开始也会继承 root 用户,接下来会通过 setuid 和 setgid 调用直接切换用户,不需要密码是因为它一开始是 root。这一切过程都和你 image 里的密码什么的无关。 |
33
zmj1316 2018-11-22 14:26:26 +08:00
@htfy96
tensorflow 官方就两种安装方法,pip 和 docker ; cuda 对 docker 也有官方 dockerfile 支持; caffe 也有 NV 有完整的 nvidia-docker 支持 所以虽然 LXD 可能是很好,但是对我这种懒人来说,docker 是唯一选择, 因为主要矛盾不在用什么虚拟化这里,而是配环境实在太 TM 麻烦了。。。。。。 |
34
NotNil1 2018-11-22 14:32:47 +08:00
有了 sudo 和有了 root 有什么区别。。。
|
35
ipwx 2018-11-22 14:44:15 +08:00
@zmj1316 我也是实践出真知。
我目前的方案是,开放所有计算节点(含 GPU )的 SSH 登陆,通过编辑 /etc/sudoers 允许用户 sudo docker 和 sudo nvidia-docker。 提供一些整合过的大型 image。 结束。 |
36
ipwx 2018-11-22 14:49:57 +08:00
@zmj1316 这样的好处有两个:
1、用户不满意我的镜像,可以字节去学 Dockerfile 怎么写呀,或者给我个 PR。 ( https://github.com/haowen-xu/docker-ml-runtime) 2、我们有很多机器。要像你的做法,难道每台机器给每台用户预先都开一个 container 吗?太麻烦了。。。还不如让用户自己解决。 3、我这边机器上有 Mesos 系统,用户可以直接跑 Dockerized Spark。后续正计划写个脚本,用户可以直接提交一个程序,作为 Mesos 任务并使用 Docker 镜像运行。 |
38
zmj1316 2018-11-22 14:57:10 +08:00
我这里的用户要求比较挑,他们不希望去了解任何 docker 的东西,要求的就是开箱即用,SSH 连上去,root 耍起来,缺了什么东西装不了的就指挥我去装;
一开始我也是直接几个 image 丢过去,让他们自己启动进去用,一 智障 说接受不了不想学怎么用,直接把整台服务器拔了电给搬自己位子用去了,所以我这操作实属无奈 |
40
zmj1316 2018-11-22 15:04:06 +08:00
顺便给 LZ 说一下,你要在 docker 容器里面执行 apt 命令,其实已经是在当虚拟机用了,因为一般 apt 这种操作是在构建镜像的时候用的,你要是缺什么东西,可以写 dockerfile 里,装到镜像里面,然后再启动容器
|
42
rizon OP @zmj1316 嗯,这样说的确是当虚拟机用了。。。可是,,,可是这样用是真的好用啊。做环境隔离和业务场景隔离,docker 和虚拟机比起来,实在是太好用了啊。。。
|
43
raysonx 2018-11-22 17:45:50 +08:00
@rizon 然而就你们这么个用法,容器的优点并没有最大发挥出来。容器最大的优点在于“一次构建,到处运行”,听起来是不是很熟悉?
|
45
wwhio 2018-11-22 20:38:41 +08:00
额,我和楼主的方法差不多,实验室里的一台 GPU 服务器被整个学院的同学分享,每个人都有自己的需求,于是最后做了几个不同的镜像,镜像里只提供 cuda + sshd,设置容器内 root 账户的密码后把密码和 ssh 端口提供给同学使用。
看了楼上的大佬发言,我大概说一下需求,借楼问下有什么好的解决方案。 1. 用户间不能互访数据,环境独立 2. 可以限制 CPU、内存、GPU 等资源 3. 不能拿到主机的 root 权限 4. 可以 apt 其实我这边的用户并没有使用 docker 的需求。另外,LXD 我会去看的,先谢谢大佬们。 |
46
passerbytiny 2018-11-23 15:45:59 +08:00
|
47
zmj1316 2018-11-23 16:58:15 +08:00
@passerbytiny docker 的文件系统应该都是有 COW 的,只开容器不修改的话基本不占用空间,占空间的只有 image 本身。
如果出现容器空间爆了,一般是有人在容器里面除了数据卷之外的地方放了大量文件, 这个我是直接告知,放在数据卷之外地方的文件不保证数据安全,所以目前他们应该还是乖乖放数据卷里面的 |
48
ipwx 2018-11-25 10:49:00 +08:00
@passerbytiny 我对容器没有多大限制,不过因为我们这边部署了 MooseFS,所以每个人的 /home 有配额限制。是按路径来的,不是按用户来的,所以当多人合作一篇论文的时候,哪怕都用 root 启动 docker,-v 挂载进去,配额还是在的。你总不好意思把你的文件放到别人 /home 下面不是?至于每台计算节点本身,不好意思,随时可能重装,不做备份警告。
|
49
ipwx 2018-11-25 10:49:46 +08:00
@passerbytiny MooseFS 是分布式文件系统,我单独开了五台服务器,和那十几台计算节点是独立的。
|
50
ipwx 2018-11-25 10:57:58 +08:00
@zmj1316 @wwhio 我一直是觉得,能够用管理的方法解决的问题就用管理的方法解决,不要什么都让技术做。所以我很强硬地推行了裸机无运行环境(包括无 CUDA )、分布式文件系统、配额,以及 Docker。配额是每个人的个人目录不超过 50 万个 inode 和不超过 2T 的数据。因为 50 万的 inode 限制,所以用 Anaconda 这种方式自己部署 Python 环境,是比较吃力的,所以他们不得不去学习 Docker 的用法。
这些措施倒是一点点来的,最后一个 Docker 化是一年前完成的。不过讲道理一开始我们这边的这套集群计算系统(计算节点和存储节点集中管理,还包括 LDAP 集中式用户系统)就是我搭起来的,也没啥太大阻力。。。目前运行良好。说实话作为用户来说,这些东西的用法都很好学,明明是计算机专业的,根本不可能学不会,不会就是懒。 |
51
ipwx 2018-11-25 11:04:31 +08:00
@passerbytiny 回到正题吧。Docker 容器空间爆炸的事情?我这边是完全不考虑的。假设某台机器因为 Docker 镜像太多而磁盘占满了,大不了重装呗。再说我会不定时运行 docker system prune,不会占满的。
你和 @zmj1316 会有这个顾虑,是因为你们俩希望 Docker 对用户透明,并且在 Docker 里面开了 sshd 让用户为所欲为。这个事情很难搞,说实话。因为 Docker 设计上就不是这么用的。 而我这边就没这个顾虑,因为我一开始就教育用户,要把文件放在 MooseFS 的路径上。Docker 容器里面想用,就挂载进去用。其实只要教给他们普通用法就行了,他们一般不会出错的。更高级的用法他们可以自学,学会了自然更不会出错了。另外我还提供一项额外服务,就是给新手一个模板脚本,在 Docker 里面启动一个 Jupyter Notebook,并且正确地挂载他们的 /home。 如果不是这么一套管理方法,10+ 的 CPU 计算节点和 3 台 GPU 计算节点,我不是得管死。。。 |
54
rizon OP @ipwx 问个事情啊,容器只能在启动之前挂载本地目录,是这样吧? 那如果一个容器在使用过程中突然发现有个目录需要映射到本地,这时候该怎么办呢?
|
55
rizon OP @ipwx 你说的“因为我一开始就教育用户,要把文件放在 MooseFS 的路径上。Docker 容器里面想用,就挂载进去用。”这句我不是很理解,moosefs 就是类似 haoop hdfs 的东西?你说的“容器里想用就挂载进去”这句话 是怎么挂载进去??
|
56
ipwx 2018-11-26 15:10:57 +08:00 1
@rizon
1. 关掉容器,删掉容器,重新建立容器。 2. MooseFS 不是类似 Hadoop HDFS 的东西。MooseFS 实现了全功能的 Posix Filesystem,可以像本地磁盘一样 mount 到本地目录上。所以可以 docker -v 挂载进容器。 你看,因为 Docker 的限制,它的用法和虚拟机是很不同的。Docker 容器的正确用法是不在容器里面放持久数据。我选择的策略就是通过 MooseFS 给用户一个跨机器能持久存储数据的“本地文件系统”,用起来和普通的本地文件系统没有区别。在此基础上,他们可以使用跨机器的 Anaconda (如果不超过 50 万个文件的配额,我特别设置的),或者使用 Docker -v 挂载。事实上我这边,用户的整个 /home 目录都是在 MooseFS 上的。 |
58
passerbytiny 2018-11-27 12:02:52 +08:00
@ipwx 你的这种方式,是要使用人自己定义镜像的,自然可以进一步限制他们不能用 yum install/apt-get install,不能编辑 /usr/local/systemd ……等等,所以没啥可担心的。然而他哪种懒惰的方式,估计是啥也不会限制,等用户一通 install/remove 后,容器占用空间就可能爆了。
|
59
ipwx 2018-11-27 15:55:03 +08:00
@passerbytiny 我不太理解,如果持久数据不存在计算节点上,爆空间有啥可担心的,大不了重装一下裸机呗。再说服务器好歹少说 3T 一般都是 6T 以上的,哪这么容易爆。
我反正没限制用户在 docker 容器里面 apt-get install。至于什么 -v 本机根目录然后 chroot,这种高端操作我这边用户都不会呢。再说哪怕搞坏了,参考前面说的,大不了重装一下呗。反正我有 ansible 脚本。 所以综上所述,唯一最重要的一点就是持久性的数据要存在分布式文件系统上,不要放在计算节点上。 |