Moby: docker build 应该支持特权操作

创建于 2013-09-18  ·  286评论  ·  资料来源: moby/moby

目前似乎没有办法在 docker run -privileged 之外运行特权操作。

这意味着我不能在 Dockerfile 中做同样的事情。 我最近的问题:我想在容器内运行保险丝(用于 encfs)。 安装保险丝已经是一团糟,有一些黑客和丑陋的解决方法(见 [1] 和 [2]),因为 mknod 失败/如果没有特权构建步骤就不受支持。

现在唯一的解决方法是手动安装,使用 run -privileged,并创建一个新的“fuse base image”。 这意味着我无法在单个 Dockerfile 中描述从官方基础镜像到完成的整个容器。

因此,我建议添加

  • 一个 docker build -privileged
    这应该与 run -privileged 做同样的事情,即删除所有大写限制

或者

  • Dockerfile 中的 RUNP 命令
    这应该......好吧..运行,但带有_P_rivileges

我尝试查看源代码,但不幸的是,我对 go 毫无用处,并且找不到合适的入口点来附加概念证明。 :(

1: https :
2: https :

arebuilder kinfeature

最有用的评论

我真的不明白为什么开发人员对 docker image 的 --privileged 有如此多的反对。
如果用户想用脚射击自己,为什么不让他们呢? 只需放置一条警告消息即可。 已经有实现同样事情的变通方法,为什么不让真正需要它的用户更容易呢?
已经4-5年了,在这方面没有任何进展。
太棒了...

所有286条评论

如果我们这样做,我更喜欢 RUNP 选项,而不是
在特权模式下运行的所有容器。

2013 年 9 月 18 日,星期三,下午 1:07,Benjamin Podszun
通知@github.com写道

目前似乎没有办法在外部运行特权操作
docker run - 特权。

这意味着我不能在 Dockerfile 中做同样的事情。 我最近的
问题:我想在容器内运行保险丝(用于 encfs)。 安装
保险丝已经被黑客和丑陋的解决方法弄得一团糟(参见 [1] 和 [2]),
因为 mknod 在没有特权构建步骤的情况下失败/不受支持。

现在唯一的解决方法是手动安装,使用
运行 -privileged,并创建一个新的“保险丝基础映像”。 这意味着我
无法描述整个容器,从官方基础镜像到完成,
在单个 Dockerfile 中。

因此,我建议添加

  • 一个 docker build -privileged
    这应该与 run -privileged 做同样的事情,即删除所有
    上限限制

或者

  • Dockerfile 中的 RUNP 命令
    这应该......好吧..运行,但带有_P_rivileges

我尝试查看源代码,但是我对 go 没用,并且找不到
不幸的是,体面的入口点可以附加概念证明。 :(

1: https :
2:#514(评论) https://github.com/dotcloud/docker/issues/514#issuecomment -22101217


直接回复本邮件或在Gi tHub上查看
.

维克多·维厄
http://vvieux.com

实际上,我们可能必须两者都做——即 RUNP + 需要一个“-privileged”
旗帜。

如果我们只依赖 RUNP(不需要“-privileged”),那么我们会
必须想知道我们何时进行构建“这个构建安全吗?”。
如果我们只依赖“-privileged”,我们就会错过信息(在
Dockerfile) 表示“此操作需要扩展权限”。

我认为两者结合是最安全的方法。

2013 年 9 月 18 日,星期三,上​​午 4:07,Benjamin Podszun
通知@github.com写道

目前似乎没有办法在外部运行特权操作
docker run - 特权。

这意味着我不能在 Dockerfile 中做同样的事情。 我最近的
问题:我想在容器内运行保险丝(用于 encfs)。 安装
保险丝已经被黑客和丑陋的解决方法弄得一团糟(参见 [1] 和 [2]),
因为 mknod 在没有特权构建步骤的情况下失败/不受支持。

现在唯一的解决方法是手动安装,使用
运行 -privileged,并创建一个新的“保险丝基础映像”。 这意味着我
无法描述整个容器,从官方基础镜像到完成,
在单个 Dockerfile 中。

因此,我建议添加

  • 一个 docker build -privileged
    这应该与 run -privileged 做同样的事情,即删除所有
    上限限制

或者

  • Dockerfile 中的 RUNP 命令
    这应该......好吧..运行,但带有_P_rivileges

我尝试查看源代码,但是我对 go 没用,并且找不到
不幸的是,体面的入口点可以附加概念证明。 :(

1: https :
2:#514(评论) https://github.com/dotcloud/docker/issues/514#issuecomment -22101217


直接回复本邮件或在Gi tHub上查看
.

@jpetazzo https://twitter.com/jpetazzo
最新博文: http :

听起来很合理。 对我来说,这个特性(能够创建设备节点)决定了在 Docker 中创建部署的能力。 如果我能提供帮助(主要是测试,我尝试查看源代码但到目前为止失败了。似乎构建文件中的可用命令是通过反射找到的,我添加了一个将 config.privileged 设置为 true 的 runp 命令,但到目前为止我无法构建和测试 -> 卡住)我很乐意投入一些时间。

我建议RUNP + build -privileged

_点亮一些烟雾信号以引起@shykes 、@crosbymichael_的注意

...然后我们必须找人来实施它,当然☺
这是您想要尝试的事情吗(当然,在核心团队的适当指导和反馈下)?

如果最后一部分是针对我的:当然,为什么不呢。 我已经在搞乱 go 代码(不是我熟悉的语言,但请参见上文:我正在尝试弄清楚发生了什么)。

有几个指针/有人可以回答一些问题,我当然会尝试一下。

我不是在 RUNP 或 build 特权上出售的。

一般来说,我不喜欢引入相同输入的不同可能构建的任何内容。 这就是为什么您不能将参数或环境变量传递给构建的原因。

具体来说,我不喜欢到处引入对“特权”的依赖,因为它指定了一组 a) 非常大和 b) 没有明确说明或定义的功能。 作为系统管理员以全有或全无的方式绕过安全性的粗略机制,这是可以的 - 当标准 docker 执行环境不够用时,这是一个“逃生舱”。 它与绑定挂载和自定义 lxc-conf 的方式类似。


@solomonstre
@getdocker

2013 年 9 月 20 日星期五下午 3:18,Benjamin Podszun
通知@github.com写道:

如果最后一部分是针对我的:当然,为什么不呢。 我已经在搞乱 go 代码(不是我熟悉的语言,但请参见上文:我正在尝试弄清楚发生了什么)。

有几个指针/有人可以回答一些问题,我当然会尝试一下。

直接回复此邮件或在 GitHub 上查看:
https://github.com/dotcloud/docker/issues/1916#issuecomment -24844868

好吧,您是否同意应该可以构建一个 docker 镜像——例如——运行保险丝?
为此,我们需要确认。

在我看来,这些构建不可能因参数而异:构建将起作用(上限没有/比现在限制更少)或失败(现状)。 相同构建文件的不同“版本”几乎没有风险,对吗?

我现在遇到了这个问题。 要构建我需要的映像,我必须执行一系列run -privileged步骤 + commit步骤,而不是build一个 Dockerfile。 理想情况下,最好在 Dockerfile 中表达镜像构建步骤。

是不是也和mknod操作有关?
如果您可以准确描述需要特权模式的操作
你的情况,这将是非常有帮助的!
谢谢,

@jpetazzo ,来自邮件列表,这是我面临的问题: https ://groups.google.com/forum/#!topic/docker -user/1pFhqlfbqQI

我正在尝试mount一个我创建的 fs(创建是为了解决 aufs 和一些关于日记的问题)在容器内。 我正在运行的特定命令是mount -o loop=/dev/loop0 /db/disk-image /home/db2inst1 ,其中/db/disk-image是用dd if=/dev/zero of=disk-image count=409600创建的,而home/db2inst1是我试图从中启动 db2 的地方。

如果我理解正确,在安装过程中,您需要一个非 AUFS 目录——或者更确切地说,支持O_DIRECT 。 如果是这种情况,Docker 0.7 应该可以解决问题,因为它将使用 ext4(和块级快照)而不是 AUFS。

+1为此。

安装需要更改内存设置和内核配置的软件包(例如 Vertica DB、WebSphere MQ)只能在特权模式下完成。

在使用“特权”运行/构建时,让我们尝试分离关注点:它可以只在构建期间需要,也可以在执行期间通过docker run或两者都需要。

如果有必要,应该可以允许构建执行一些需要更多(或更多)权限的步骤。 我需要在一个项目中使用它,并且必须将 Dockerfile 的一半转换为 shell 脚本,该脚本调用构建并继续以特权模式构建事物,因此拥有“特权”构建会很有用。

但是,我们不应该默认进入特权模式,这样我们就可以使用 sysctl 更改某些设置。 这应该通过图像配置或通过传递给docker run命令行参数来完成。

对。 @orikremer ,您有关于 Vertica DB 和 WebSphere MQ 试图更改的参数的详细信息吗?

如果它是 /sys 或 /proc 中的内容,最好的解决方案可能是在那里放置一些模型,而不是切换到特权模式(因为无论如何都不会保留更改)。

从长远来看,模拟文件系统可能会捕获更改并将它们转换为 Dockerfile 指令,指示运行时“嘿,这个容器需要这样或那样的调整”。

@jpetazzo创建图像已经有几天了。 AFAIR Vertica 抱怨它没有足够的内存,并且两者都试图更改最大打开文件数。
我将尝试使用 Dockerfile 重新创建图像并报告。

注意到问题 #2080,因为它是相关的。

@jpetazzo开始在没有 -privileged 的​​情况下重新创建图像。 目前有两个问题:

  • 在limits.conf 中很好:Vertica 将“dbadmin - nice 0”添加到/etc/security/limits.conf。 在非特权容器中运行时尝试切换到该用户时,出现“无法打开会话”错误。 在特权容器中,切换用户可以正常工作。
  • max open files:由于容器中所需的最大值高于主机中设置的最大值,因此我必须更改主机上的 /etc/init/docker.conf 并设置“limit nofile”,然后在容器中设置 ulimit -n。 这是正确的方法吗?

当尝试切换到该用户时,

切换是如何发生的? 我不明白-privileged如何帮助用户切换; 我可能在这里遗漏了一些东西:-)

最大打开文件数

如果我理解正确,垂直安装程序会尝试将打开文件的最大数量设置为一个非常高的数字,并且只有在 Docker 以如此高的数字 _or_ 和-privileged标志启动时才有效; 对?

切换用户 - su dbadmin因该错误而失败。
我能够通过以下方式重现:

  • 拉一个新镜像 (centos-6.4-x86_64) 并非特权运行
  • 用户添加测试用户
  • 编辑/etc/security/limits.conf,添加“testuser - nice 0”
  • 尝试su testuser --> 应该失败并显示“无法打开会话”
    在 -privileged 容器中su testuser工作正常。

最大打开文件数 - 正确。 安装程序尝试设置为比主机更高的数字。 只有通过增加主机设置或启动 -privileged 才能做到这一点。

我只是尝试使用以下 Dockerfile:

FROM ubuntu
RUN useradd testuser
RUN echo testuser - nice 0 > /etc/security/limits.conf
CMD su testuser

它工作正常。 您使用的图像的确切名称是什么?
(我试过centos-6.4-x86_64但看起来我不能拉它!)

@lukewpatterson你能分享一下你是如何让循环文件系统在你的容器内工作的吗?

@jpetazzo运行这个

FROM backjlack/centos-6.4-x86_64
RUN useradd testuser
RUN echo 'testuser - nice 0' >> /etc/security/limits.conf
RUN su testuser
RUN echo 'test' > ~/test.txt

失败:

ori<strong i="10">@ubuntu</strong>:~/su_test$ sudo docker build .
Uploading context 10240 bytes
Step 1 : FROM backjlack/centos-6.4-x86_64
 ---> b1343935b9e5
Step 2 : RUN useradd testuser
 ---> Running in b41d9aa2be1b
 ---> 2ff05b54e806
Step 3 : RUN echo 'testuser - nice 0' >> /etc/security/limits.conf
 ---> Running in e83291fafc66
 ---> 03b85baf140a
Step 4 : RUN su testuser
 ---> Running in c289f6e5f3f4
could not open session
Error build: The command [/bin/sh -c su testuser] returned a non-zero code: 1
The command [/bin/sh -c su testuser] returned a non-zero code: 1
ori<strong i="11">@ubuntu</strong>:~/su_test$

我打开的调试PAM模块(通过添加debugpam_limits.so管线/etc/pam.d/system-auth ),安装syslog ,试图su再次,这是我在/var/log/secure

10 月 7 日 14:12:23 8be1e7bc5590 su:pam_limits(su:session):从“/etc/security/limits.conf”读取设置
10 月 7 日 14:12:23 8be1e7bc5590 su:pam_limits(su:session):process_limit:处理 - 用户好 0
10 月 7 日 14:12:23 8be1e7bc5590 su:pam_limits(su:session):从“/etc/security/limits.d/90-nproc.conf”读取设置
10 月 7 日 14:12:23 8be1e7bc5590 su:pam_limits(su:session):process_limit:为 DEFAULT 处理软 nproc 1024
10 月 7 日 14:12:23 8be1e7bc5590 su:pam_limits(su:session):无法为“nice”设置限制:不允许操作

然后我strace d su进程,发现以下系统调用失败:

setrlimit(RLIMIT_NICE, {rlim_cur=20, rlim_max=20}) = -1 EPERM (Operation not permitted)

反过来,这会导致pam_limits模块报告失败; 这会阻止su继续。
有趣的是,在Ubuntu上, pam_limits未启用了su默认; 并且即使您启用它, setrlimit调用也会失败,但su仍然会继续工作。
这可能与审计代码有关,我不确定。

现在,为什么setrlimit失败了? 因为容器缺少sys_resource功能,这是提高任何类型限制所必需的。

我想我会注释掉limits.conf指令。
(顺便说一句,将内容直接添加到limits.conf是不好的做法;我认为它应该转到limits.d的单独文件。)

注意:由于您已经提高了 Docker 的打开文件数限制,您还可以提高最大优先级的限制; 这也应该有效!

我希望这有帮助。

在那个 Dockerfile 中,你有以下一行:

RUN su testuser

没有可以执行此操作的命令(并且它不会将任何生成的 shell 应用于后续的 RUN 命令),所以如果它在尝试打开 shell 时真的失败并且没有在某个交互式的地方这样做是有道理的,我不会感到惊讶(因为docker build不是交互式过程)。 我现在没有时间确认,但可能值得尝试将实际命令传递给su

@jpetazzo感谢您的详细描述。 我将尝试提高 Docker 的最大优先级,看看是否有帮助。

(顺便说一句,将内容直接添加到limits.conf 是不好的做法;我认为它应该放在limits.d 中的一个单独文件中。)

同意,但由于这是将它放在那里的 Vertica 安装程序代码,我正在尝试解决这个问题。

@tianon如果我在交互式 shell (/bin/bash) 中运行它,

抱歉,我觉得还是值得一试的。

不过,关于该行在 Dockerfile 中没有多大意义的观点仍然适用。 你可能想要更像这样的东西(在你弄清楚限制问题之后):

RUN su testuser -c 'echo test > ~/test.txt'

@tianon你是对的,这没有多大意义。 那只是为了证明 su 本身失败了。

回到最初的讨论:我相信从安全的角度来看(并且有用!)在构建过程中允许setfcapmknod功能(并且可能在常规容器执行中作为好)。 有没有人看到任何可能源于此的问题?

@jpetazzo恰恰相反! 它将解决我遇到的许多问题。 我认为这对于想要运行行为/看起来更像真机的 Docker 容器的人来说是必要的。

好的! 如果这对您没问题,我将关闭此问题以支持 #2191,“在所有容器中启用 mknod 和 setfcap 功能”然后 :-)

我们知道这些场景吗?

2013 年 10 月 13 日星期日下午 12:22,unclejack [email protected]写道:

2191 https://github.com/dotcloud/docker/issues/2191没有解决这个问题

所有需要 docker build -privileged 的​​场景的问题。


直接回复本邮件或在Gi tHub上查看
.

@jpetazzo https://twitter.com/jpetazzo
最新博文:
http://jpetazzo.github.io/2013/10/06/policy-rc-d-do-not-start-services-automatically/

@jpetazzo当您想使用 Dockerfile 构建操作系统映像时,这是必需的。

我在编辑时错误地删除了我的评论。

请看看如果不在 Dockerfile 中做所有事情,它会是什么样子:

from ubuntu:12.04
run apt-get update
[... a few more run commands]
add build.sh /root/build.sh

编译文件

docker build -t mybuild .
docker run -i -t -privileged -cidfile mybuild.cid mybuild /root/build.sh
buildcid=`cat mybuild.cid`
rm mybuild.cid
docker commit $buildcid mybuild-final

这只是迫使我解决 Dockerfile 或docker build -privileged缺少runp的问题,从而使 Dockerfiles 变得无用,并迫使我编写一个工具来复制类似 Dockerfile 的功能。

显然,Dockerfile 与runpdocker build -privileged一起使用会更有用:
运行示例:

from ubuntu:12.04
run apt-get update
[... a few more run commands]
add build.sh /root/build.sh
runp /root/build.sh

docker build -privileged示例:

from ubuntu:12.04
run apt-get update
[... a few more run commands]
add build.sh /root/build.sh
run /root/build.sh

@unclejack :抱歉,我的问题不够准确!
我的意思是“你到底需要哪个权限(在 mknod 和 setfcap 之上)?”

@jpetazzo很难说,我必须以某种方式对其进行审核才能弄清楚需要什么。 挂载文件系统,使用环回挂载块设备和其他一些东西。

在构建映像时至少有三个不同的需求: docker build期间所需的权限,使用 docker 运行容器时所需的权限,以及在构建、运行或两者(如 sysctls 等)过程中对进程的运行时需求.

我认为让docker build -privileged (或runp仅对真正需要它的命令使用 -privileged 模式)会很有用。

啊,坐骑绝对是一个大的。 这是一个非常有效的用例,我们_可能_不想在一般情况下允许它们。 我重新打开这个问题。

@jpetazzo RE:PAM 模块(我也在安装 Vertica)您是否建议在从 lxc.cap.drop 中取出 sys_resource 后重新编译 docker?

也许其中一些限制可以通过 docker.conf 文件设置?

应该考虑到 Docker 本身可能运行在一组有限的功能中,因此 Docker 可能无法将这些权限委派给其容器。 这在嵌套 Docker 场景中尤其正确,应该发出 #2080 land——这可能允许非特权嵌套 Docker。

并不是说这会改变任何东西,除了诸如“runp”或“-priviledged”之类的解决方案可能无法保证在所有 Docker 环境中都能成功。 在添加此类命令和记录它们时应该考虑这一点。

@ramarnat @jpetazzo只是为了关闭 Vertica 安装和良好级别问题的循环,
我确实尝试在 docker.conf 中设置很好的限制,但这对我不起作用,我被迫以 bash 特权运行并手动安装它。

@orikremer @jpetazzo我能够通过从 lxc_template.go 中删除 sys_resource 并重新编译 docker 来运行安装。 我可以在那里提出拉取请求,但我会等待其他人对从 lxc 配置中删除它的安全影响发表意见。

@ramarnat :根据场景,有些人会认为删除 sys_resource 就可以了; 对于其他一些人来说,这将是一个问题。

一种可能性是将基本限制增加到更高的水平(文件描述符也是弹性搜索的一个问题)。 这就像断言“最小的 Docker 运行时应该能够处理 1,000,000 个文件描述符”。 如果 Docker 在启动时无法提高限制,它将发出警告并继续(就像对内存/交换控制器组所做的那样)。

不过,这并不能解决挂载/循环场景(我仍在沉睡于此)。

@jpetazzo可能会提供一种方法来覆盖 lxc_template.go 中的硬编码值。 命令行 -lxc_conf 已经有一些适合场景的东西,但它不适用于这些 lxc 配置指令的 .drop 性质 - 我试过了!

嗯,这是一种可能性,但这也是打破未来跨不同容器化系统的兼容性的好方法:-) 我们会看看是否找不到更好的方法。

我们可以在非特权模式下将 /dev/loop* 列入白名单吗? 我想问题是它可能让我访问其他容器的循环挂载文件,甚至主机的...

@solomonstre
@docker

2013 年 10 月 17 日星期四下午 6:09,Jérôme Petazzoni
通知@github.com写道:

嗯,这是一种可能性,但这也是打破未来跨不同容器化系统的兼容性的好方法:-) 我们会看看是否找不到更好的方法。

直接回复此邮件或在 GitHub 上查看:
https://github.com/dotcloud/docker/issues/1916#issuecomment -26565782

@jpetazzo是的,但我认为

@solomonstre关键是必须有一种方法允许docker build在特权模式下构建。 允许访问 /dev/loop* 对我的特定用例没有帮助。

@solomonstre :将 /dev/loop 列入白名单,恕我直言,这是一个很大的

我知道有些构建需要循环设备、安装和其他东西。 让我们回顾一下我们的选择:

  1. docker build -privileged
    方便,但在“正常构建”和“特权构建”之间划清界限。 如果您碰巧有一个非常有用的镜像需要特权构建器,那么在公共构建器上构建它会很困难。 例如,如果有人启动服务来自动化构建,他们可能不会提供特权构建(或者他们将不得不使用额外的保护措施)。
  2. 在构建器中稍微放宽权限
    这意味着(至少)启用 cap_sysadmin(这让偏执的我有点颤抖),并且可能为每个构建器提供一两个循环设备。 这将限制并行运行的构建器总数; 但这没什么大不了的,因为构建应该是快速的,更重要的是,活跃的过程。 IE 如果您有 50 个并行运行的构建,除非您有一台带有 kickass I/O 子系统的机器,否则这些构建不会有太大进展。
  3. 将构建包装在另一层虚拟化/隔离中。
    不要直接在 Docker 中运行构建,而是运行类似 QEMU-in -Docker 或 UML-in-Docker 的东西。 从 Docker 开发人员的角度来看,这是一个很酷的解决方案,因为它意味着不需要额外的工作; 从 DOcker 用户的角度来看,这是一个糟糕的解决方案,因为这意味着要处理另一层复杂性。

我想知道正确的解决方案是否可能是允许docker build -privileged`,同时考虑允许透明实现选项 3 的钩子。假设我是一个“docker build provider”:如果有人请求特权构建,我所要做的就是在沙盒环境中的某个地方插入一些东西来运行他们的构建过程(QEMU 和 UML 是明显的候选者,但其他人也可能工作;它们只是方便的例子)。

你们有什么感想?

@backjlack ,请问您在构建后如何使用该容器? 什么
当您“docker run”它时会发生什么,应用程序是什么? 只是
试图了解这方面的用例。

2013 年 10 月 18 日星期五上午 9:59,Jérôme Petazzoni
通知@github.com写道

@solomonstre https://github.com/solomonstre :白名单 /dev/loop 是,
恕我直言,一个很大的禁忌,因为使用 DM 分支,它会给读/写
访问所有内容(因为 DM 分支的默认行为是使用
循环设备来存储池)。

我了解某些构建将需要循环设备、安装和其他
事物。 让我们回顾一下我们的选择:

  1. docker build -privileged 方便,但划清界限
    “正常构建”和“特权构建”。 如果你碰巧有一个非常
    需要特权构建器的有用图像,将很难
    将其构建在公共构建器上。 例如,如果有人启动了一项自动化服务
    构建,他们可能不会提供特权构建(或者他们将拥有
    使用额外的保护措施)。
  2. 在构建器中稍微放宽权限这意味着(至少)
    启用 cap_sysadmin(这让偏执的我有点颤抖),也许
    给每个建造者一个或两个循环设备。 这将限制总
    并行运行的构建器数量; 但这没什么大不了的,因为
    构建应该是快速的,更重要的是,活跃的过程。
    IE 如果你有 50 个并行运行的构建,除非你有一台机器
    使用 kickass I/O 子系统,这些构建不会有太大进展。
  3. 将构建包装在另一层虚拟化/隔离中。
    与其在 Docker 中直接运行构建,不如运行类似
    QEMU-in -Docker 或 UML-in-Docker。 这是来自 Docker 的一个很酷的解决方案
    开发人员的观点,因为这意味着不需要额外的工作; 这是一个穷人
    从 DOcker 用户的角度来看的解决方案,因为这意味着处理
    另一层复杂性。

我想知道正确的解决方案是否可能是允许 docker build-privileged`,
同时,考虑允许透明的钩子
选项 3 的实现。假设我是一个“docker build provider”:如果
有人请求特权构建,我所要做的就是插入
某处可以在沙盒中运行他们的构建过程
环境(QEMU 和 UML 是明显的候选者,但其他人可能会工作
也; 它们只是方便的例子)。

你们有什么感想?


直接回复本邮件或在Gi tHub上查看
.

+1 - 我想看到 mknode 安装保险丝(用于安装 S3 存储桶)的能力或在 Dockerfiles 中执行特权运行的能力。 尚不确定最佳解决方案是什么。

+1。 关于这个问题的任何更新?

+1
2013 年 11 月 17 日晚上 11:31,“yukw777”通知@github.com 写道:

+1。 关于这个问题的任何更新?


直接回复本邮件或在Gi tHub上查看
.

我在尝试安装 Java 时也遇到了 Fuse 问题,我对解决方案很感兴趣。 我尝试了此处建议的解决方法https://gist.github.com/henrik-muehe/6155333,但它在 Raspberry Pi 上的 docker 上对我不起作用。

@jpetazzo :我喜欢在探索长期解决方案的同时实施 -privileged 标志的总体策略。 为此,我提交了一个 pull request 来实现这个功能。 请注意,截至目前,它没有实现本线程前面讨论的“RUNP”命令。

(让我“交叉发布”这个,因为人们最终可能会在这里寻找解决方法)

如果您实际上没有使用设备文件(但它只是一个 post-inst 脚本的一部分,就像使用 fuse 包的情况一样),您可以执行以下操作:

fakeroot apt-get ...

或者:

dpkg-divert --local --rename --add /sbin/mknod && ln -s /bin/true /sbin/mknod`

我确信这是善意的,但第一个评论/我的报告已经包含了两个解决方法。
公平地说,您在列表中添加了新的,但问题不在于“无法安装保险丝”,阅读第一篇文章应该可以帮助那些无论如何都只需要安装软件包的人。

真正的问题是“我需要调用 mknod”(或更通用:我需要迄今为止失败的特权操作)。

@jpetazzo这可以解决这个问题,对吗? https://lwn.net/Articles/564977/ - 在那之前,我会选择 3) 因为隔离设备访问_是另一层复杂性,它必须在某处进行管理。

我也不认为回路安装或保险丝是必要的功能。 为使用空间中的容器提供 root 权限以挂载用户空间中的文件系统(保险丝:实现运行,循环:图像文件是),这感觉很疯狂。

如果您需要挂载文件系统映像或熔断 fs,您可以将其挂载到容器外并将其用作卷/绑定挂载。 尽管在 docker 本身中支持和管理远程文件系统可能是一个不错的功能。 也许是一个 dockerfile MOUNT/挂载点。

@discordianfish 3) 几乎是一个非解决方案。

#2979 会帮助解决这个问题吗?

我也在等待解决这个问题,但不是因为 mknod。 我们正在运行带有 rpms 的 centos 容器,这些容器使用 /etc/security/limits.d/ 为用户设置限制,我目前正在使用包括以下内容的大锤解决方法:

RUN /bin/sed --in-place -e "s/^\s\?session.*pam_limits.so.*/\#\0/g" /etc/pam.d/*

在我的 Dockerfile 的顶部。 (我们只是原型设计,别担心:))

@jpetazzo我尝试了你建议的两个选项。 我正在尝试使用构建图像“oracle_xe”

sudo docker build - privileged -t oracle_xe 因为在我的 Dockerfile 中我想运行这两个命令

RUN mount -o remount,size=3G /dev/shm
运行挂载 -a

但这不起作用,我不知道我使用的语法是否不正确,我得到的错误是
提供但未定义的标志:-privileged

我也尝试使用 RUNP 的第二种选择,但这也不起作用,当我构建图像时,它会跳过那一步说

跳过未知指令 RUNP。 我可以向您发送我正在尝试构建的 Dockerfile。 请帮我解决这个问题。

谢谢。

我认为 RUNP 和“build --privileged”都没有实现。
如果可能,请毫不犹豫地共享 Dockerfile; 它可能很有用,所以
我们可以为您提供“最差”的解决方法:-)

在星期三,2014年4月9日7:44 AM,Manoj7 [email protected]写道:

嗨 jpetazzo 我尝试了你建议的两个选项。 我正在尝试构建
图像“oracle_xe”使用

sudo docker build - privileged -t oracle_xe 因为在我的 Dockerfile i
想运行这两个命令

RUN mount -o remount,size=3G /dev/shm
运行挂载 -a

但我那不起作用,我不知道我使用的语法是否是
不正确。 我也尝试使用 RUNP 的第二个选择,但也没有
工作,当我构建图像时,它会跳过那一步说
跳过未知指令 RUNP。 我可以把我的 Dockerfile 发给你
试图建立。 请帮我解决这个问题。

谢谢。

直接回复本邮件或在Gi tHub上查看
.

@jpetazzo https://twitter.com/jpetazzo
最新博文:
http://jpetazzo.github.io/2014/03/23/lxc-attach-nsinit-nsenter-docker-0-9/

@jpetazzo ,我想在我的 Dockerfile 中执行“RUN sudo umount /etc/hosts” - 是否有“最差”的解决方法? ;)

@jpetazzo

我用来构建 oracle_xe 镜像的 Dockerfile

*

维护者* * * * * * *

添加oracle-xe-11.2.0-1.0.x86_64.rpm.zip /appl/oracle/xe/oracle-xe-11.2.0-1.0.x86_64.rpm.zip
RUN mount -o remount,size=3G /dev/shm
运行挂载 -a
运行 cd /appl/oracle/xe && 解压 oracle-xe-11.2.0-1.0.x86_64.rpm.zip
运行 cd /appl/oracle/xe/Disk1 && rpm -Uvh oracle-xe-11.2.0-1.0.x86_64.rpm
运行 cd /appl/oracle/xe && rm oracle-xe-11.2.0-1.0.x86_64.rpm.zip
ENV ORACLE_HOME /u01/app/oracle/product/11.2.0/xe
ENV ORACLE_SID XE

我尝试的第一件事是

须藤 docker build -privileged -t oracle_xe 。

这不起作用,然后我尝试使用 RUNP
RUNP mount -o remount,size=3G /dev/shm
RUNP 挂载 -a
这也不起作用,这两个步骤被跳过了。

@gatoravi :不幸的是,卸载 /etc/hosts 并不容易。 为什么你需要这样做? (我知道您可以有非常正当的理由,但我很想听听他们为您提供最好的解决方法......)

@Bhagat7 :对! 问题:在运行时_和_安装时,您需要更大的 /dev/shm,还是只需要运行时? 如果是在构建时,哪一步失败了,如何失败?

@jpetazzo作为工具构建过程的一部分,我想向 /etc/hosts 添加一个新的 IP 地址。
类似于echo $IP $HOST >> /etc/hosts.

如果我使用docker run --privileged然后执行sudo umount \etc\hosts我可以做到这一点,但看起来我无法使用docker commit提交,因此我必须重复umount每次运行容器时都手动执行步骤。

我想以某种方式使\etc\hosts可写并使其持久化,似乎无法找到使用docker commit或 Dockerfile 的方法。

@jpetazzo

我有这个问题

bash-4.1#/etc/init.d/oracle-xe 配置
指定将用于 Oracle Application Express [8080] 的 HTTP 端口:

指定将用于数据库侦听器的端口 [1521]:1521

指定用于数据库帐户的密码。 注意同样
密码将用于 SYS 和 SYSTEM。 Oracle 建议使用
每个数据库帐户的不同密码。 这可以在之后完成
初始配置:
确认密码:

您是否希望在启动时启动 Oracle Database 11g Express Edition (y/n) [y]:y

启动 Oracle Net Listener...完成
配置数据库...完成
启动 Oracle Database 11g Express Edition 实例...完成
安装成功完成。
bash-4.1#cd /u01/app/oracle/product/11.2.0/xe/bin
base-4.1#sqlplus
输入用户名:system
输入密码: * **
但我收到这个错误
ORA-01034: ORACLE 不可用
ORA-27101: 共享内存领域不存在
Linux-x86_64 错误:2:没有那个文件或目录
进程 ID:0
会话 ID:0 序列号:0
df -h 返回容器内
已使用的文件系统大小 Avail Use% Mounted on
tmpfs 64M 0 64M 0% /dev/shm

因此,当我将 tmpfs 的大小增加到 3G 时,我没有收到此错误。 我通过运行容器来解决它
sudo docker run -privileged -i -t oracle_xe /bin/bash. 我在容器内运行了 2 个挂载命令。 但我不想那样做,而是想将它们放在我的 Dockerfile 中并构建它。

@gatoravi :好的,明白了。 还有两个问题:在构建期间,您是否需要 /etc/hosts 中的额外主机,还是仅在运行期间? 你为什么需要它?

@Bhagat7 :对不起,我还没有一个优雅的解决方案:-(我建议有两个Dockerfiles:

  • 第一个完成所有步骤(除了需要更大的 /dev/shm 的那个),并定义一个 CMD 来检查容器是否在特权模式下运行,挂载更大的 /dev/shm,并运行特殊的命令;
  • 第二个 Dockerfile 来执行进一步的步骤(除非你在运行时还需要 /dev/shm,那么现在你需要一个特权的东西)。

@jpetazzo我们想为我们的用户提供一个带有可编辑 /etc/hosts/ 的图像(/container),以便他们可以构建修改该文件的代码:) 至于为什么我们需要添加主机,我'老实说,我不太确定,我们将其作为安装的一部分来帮助将某些主机名指向 IP 地址。

@Bhagat7我已经能够使用以下组合在

  1. https://github.com/wnameless/docker-oracle-xe-11g
  2. 在主机...
sysctl -w kernel.msgmni=4096
sysctl -w kernel.msgmax=65536
sysctl -w kernel.msgmnb=65536
sysctl -w fs.file-max=6815744
echo "fs.file-max = 7000000" > /etc/sysctl.d/30-docker.conf
service procps start

@mikewaters 非常感谢您的回复。 我认为您在 Ubuntu 之上构建了 Oracle XE。 但我正在尝试在 Centos 上构建它。

@jpetazzo 非常感谢您的建议

嗨,大家好,

我正在使用需要写入/dev/shm google-chrome,这似乎通常是 777,这里是 755。 我尝试向/etc/fstab添加特定配置,但无法运行mout -a以将修改应用于构建。 当然,我尝试了基本的chmodchown但在构建时也无法做到。

如果我在--privileged模式下登录时使用我的命令,则一切正常。 但正如其他人所解释的那样,我需要在构建时执行此操作。

有什么建议吗?

谢谢你。

@tomav "/dev/shm" 权限问题实际上是#5126,已在#5131 中修复,并且已经合并到master(并将在下一个版本中)

谢谢@tianon。

今天我有了这个想法:我想要一个容器来管理我的数据量。 很简单,但由于我使用的是 vps,我希望这些卷加密,但像往常一样清晰地提供给其他容器。 关键是,只是为了在虚拟磁盘上没有明确的数据,并且通过删除密钥来快速销毁。

我遵循了本文中有关创建 cryptfs 以将容器放入其中的一些精美记录的步骤: https ://launchbylunch.com/posts/2014/Jan/13/encrypting-docker-on-digitalocean/

请注意,我 _not_ 试图这样做,但实际上有一个装有 cryptfs 的容器:
所以加密的文件系统应该在构建过程中通过 docker 创建、挂载和格式化。

失败了:

  • 当我试图找到一个循环设备时:
+ losetup -f
losetup: Could not find any loop device. Maybe this kernel does not know
       about the loop device? (If so, recompile or `modprobe loop'.)

  • 奇怪的是,完全相同的 dockerfile _sometimes_ 成功找到了一个循环设备,然后:
+ losetup -f
+ LOOP_DEVICE=/dev/loop1
+ losetup /dev/loop1 /cryptfs/disk
+ cryptsetup luksFormat --batch-mode --key-file=/etc/cryptfs/random /dev/loop1
setpriority -18 failed: Permission denied
/dev/mapper/control: mknod failed: Operation not permitted
Failure to communicate with kernel device-mapper driver.
Cannot initialize device-mapper. Is dm_mod kernel module loaded?

有没有办法解决这个问题? (除了将磁盘安装/格式化步骤移动到run

+1 这对“docker in docker”环境特别有用

+1 对此,iptables 在非特权模式下不起作用,这会导致任何尝试设置防火墙规则的操作失败。

@PerilousApricot :但是请注意,即使您可以在RUN设置 iptables 规则,它也会立即丢失,因为图像仅保存文件系统的状态。 它不知道正在运行的进程、网络路由、iptables 规则等。

我没问题,因为容器只有特定的端口
转发,我不关心防火墙,我主要只是想要
安装程序完全能够成功

安德鲁·梅洛

@PerilousApricot我明白了! 在这种情况下,将iptables符号链接到/bin/true怎么样? 这也应该让安装人员感到高兴。 (或者一些类似的欺骗安装程序的技巧?)

我试过了,但安装程序还需要解析来自
iptables,所以没那么容易 :)

好的,我知道这越来越黑了,但是 - 换一个假的iptables怎么样? 哪个会产生一些虚拟输出?

我完全理解这不是很好; 但说真的,应该首先修复那种安装程序:)

docker 用例中的 docker 将我带到了这里。 嗯,具体来说,lxc 中的 docker,因为我们的开发环境使用 lxc,我希望开发人员能够在 lxc 中构建图像。

我也希望在 docker 中为 docker 服务。 有一个图像需要在应用程序运行之前被拉取,它相当大,我宁愿将它作为docker build一部分拉取和缓存,而不是需要经常拉取和/或提交将其拉出的容器。

此功能是必备的恕我直言, RUNPbuild-privileged会很棒。

我遇到的现实/生产场景是在中间容器中使用 Puppet 配置构建的 Docker 镜像。 在某些需要提升功能的服务上,构建失败,需要容器在-privileged ,使用ENTRYPOINTCMD重新应用 puppet 脚本。

这会延迟容器内实际服务的启动时间,因为需要构建 puppet 配置然后应用以确保正确的状态(这很耗时),并且正在运行的容器_可能_不需要在实际中运行-privileged模式,但仅在构建期间评估中间容器中的某些状态期间。

我希望以上是有道理的。

@jpetazzo我正在尝试在 centos6 之上构建一个网络服务器。 我被困在通过 dockerfile 配置 iptable 规则。 它类似于@PerilousApricot的问题。

顺便说一句:我不是为了实施诸如假 iptables 之类的黑客攻击。

@pmoust :你有关于哪些构建操作需要提升权限的详细信息吗? 我可能会建议回避这个问题,我完全意识到这可能不会让你满意; 但尽管如此,我很乐意了解什么样的安装程序/构建器可能需要这些权限......

@passion4aix :请注意,如果您在 Dockerfile 中设置了 iptables 规则,它们将不会被保存。 Docker 只保存文件系统状态,不保存路由/过滤/运行进程......有一些方法可以使用“sidekick”容器设置 iptables 规则。 这对你来说可能很有趣吗?

@jpetazzo Bitrock 安装程序就是一个例子。 它需要将 /tmp 挂载为 tmpfs。 你可能想看看http://answers.bitrock.com/questions/3092/running-installer-inside-docker

@jpetazzo或基本上任何 openstack 安装程序

我在尝试在 Docker 容器中运行 TokuMX 时也遇到了类似的问题,因为 TokuMX 需要禁用“transparent_hugepage”内核选项。

这个问题有什么进展吗? 它已经一年多了,看看评论,大多数人都使用过从 Dockerfile 运行特权操作。

我个人不会选择使用“--privileged”解决方案进行构建。 RUNP 解决方案更好,因为那时您只能以特权用户身份运行某些操作,而不是以特权身份运行整个安装。 这样至少你必须考虑什么时候使用 RUNP 并且只在需要的时候使用它。

在我看来,问题不再是如果应该添加此选项,而是仅当它完成时。 那么,我们什么时候可以期待这个功能呢?

@diversit他们必须耦合。 因此,命令行上的--privileged将能够使用RUNP ,否则对于构建不受信任的代码(包括 DockerHub)的人来说,这将是一场安全噩梦。

但请记住,您可以在 Dockerfile 语法之外手动执行此操作。 构建过程是读取 Dockerfile,从中创建一个容器,并将其提交回镜像。

@deas :我认为这可以通过执行VOLUME /tmp来解决。

@PerilousApricot :你能详细说明一下吗? 我不明白为什么任何类型的安装程序都需要特殊权限。 (是的,我是一个老顽固的 Unix 家伙,这是我的缺点之一:D)

@diversit :对于这种特定情况,我认为机器管理员应该在构建之前禁用透明大页面。 因为如果允许构建器这样做,它将在全局范围内执行(对吗?),并且可能会破坏其他可能需要该功能的容器。 你明白我的意思吗? 如果构建容器 X 中断运行容器 Y 会很糟糕......

每个人:我完全理解当 Dockerfile 不工作时非常令人沮丧,你需要的只是这个--privileged / RUNP标志。 但是如果我们开始使用特权构建,它会破坏大量的东西(例如在 Docker Hub 上的自动构建!),所以这就是我们对它感到非常糟糕的原因。 对于它的价值,我愿意调查所有需要特权构建的场景并帮助修复它们:-)(因为我个人认为这些安装程序已损坏!)

@jpetazzo许多/大多数 openstack 部署工具(例如 https://openstack.redhat.com/Main_Page)设置 iptables 规则。 我希望能够滚动/部署应用程序的容器化版本,因此能够构建 dockerfile 并一次性完成对我来说很重要。 我知道 iptables 规则不是通过本地容器化过程保留的,而是通过 iptables-save 保留的,因此在 CMD 过程中简单的 iptables-restore 将导致规则重新加载。 仅仅“存根”iptables 要复杂得多,因为许多部署工具使用像 puppet 或 Chef 这样的 CI 工具来执行实际部署,所以你需要以某种方式制作一个兼容的存根,最终模拟所有“真实”iptables 命令的输入/输出。

此外,我认为这是一个公平的权衡,“如果你有一个需要特权构建的 Dockerfile,你就会失去功能 X、Y、Z”

如果没有足够的共享内存空间,Oracle xe 将无法运行。 所有帐户都是 remountimg tmpfs 与 enuf 空间使 Oracle xe 乐于启动并完成其配置..(对于那些有见识的人,抱怨目标内存限制的是“/etc/init.d/oracle-xe configure”步骤传闻是通过增加安装尺寸来实现的)

在构建期间
运行卸载 tmpfs
失败
umount: /proc/kcore: 必须是超级用户才能卸载

给我 RUNP 或给我死亡.... 或.... 告诉我什么可以做不同的:)

我的例子是无效的; @jpefazzo仍然存在 :) 我的 Oracle 设置导致了问题,似乎不需要调整 tmpfs 大小......至少对于初始安装。

我在 CentOS 7.0 中遇到了iptables问题,只有在run ning 和--privileged https://github.com/docker/docker/issues/3416时才能解决

如果不支持特权构建,我不确定如何解决此问题

Step 24 : RUN iptables -I INPUT -p tcp --dport 80 -j ACCEPT
 ---> Running in 74ebc19b6935
iptables v1.4.21: can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.

@buley我相信在#8299 中添加security-opts可以在没有--privileged情况下做到这一点

@jpetazzo我不知道如何使用VOLUME /tmp解决 Bitrock 安装程序的问题。 这可能适用于构建,但它也会使/tmp绕过基于该图像的所有容器的 AUFS 分层,对吗? 归根结底,似乎根本原因应该在 AUFS 中解决。

这是我的用例:我想在 docker 容器中构建一个 chroot 环境。 问题是debootstrap无法运行,因为它无法在 chroot 中挂载 proc:
W: Failure trying to run: chroot /var/chroot mount -t proc proc /proc
mount: permission denied
如果我run --privileged容器,它(当然)工作......
我真的真的很想在 Dockerfile 中对 chroot 进行 debootstrap(更干净)。 有没有办法让它工作,而无需等待 RUNP 或 build --privileged?

非常感谢!

+1 表示 --privileged 或安装。 需要自动化构建 glusterfs

这影响了我从 Bitnami Tomcat 安装程序构建映像的努力。 99% 的安装过程运行没有问题,但是,当它第一次尝试启动 tomcat 时,失败并在 catalina-daemon.out 中显示以下输出:

set_caps: 设置能力失败
检查您的内核是否支持功能
用户“tomcat”的 set_caps(CAPS) 失败
返回值为 4 的服务退出

我可以在我使用“--cap-add ALL”创建的容器中手动成功运行 Tomcat 安装程序。 我不能使用“docker build”来创建我可以使用“docker run”然后“docker commit”手动创建的图像,这似乎很奇怪。 在构建过程中使用的容器应该具有您可以使用“docker run”创建的容器的所有功能。

@gilbertpilz为了确保构建的可移植性和安全性,他们非常明确地不能这样做。

@ cpuguy83 - 这没有任何意义。 如果我这样做,我可以手动构建我想要的图像:

docker run --cap-add ALL .... /bin/bash
bitnami-tomcatstack-7.0.56-0-linux-x64-installer.run ...
出口
码头工人提交....

我所要求的只是能够使用“docker build”来做我在这里手动做的事情。 如果我能以一种方式而不是另一种方式创建图像,我就看不到如何“确保”“可移植性和安全性”。

好的,让我给你一个 Dockerfile,它将主机的 /etc/passwd 挂载到构建器中,并且恰好将它发送给我。

这东西可能很危险。
另请注意,--privileged(和--cap-add ALL)使容器中的用户可以完全控制主机。

允许这些事情会损害整个 DockerHub

@ cpuguy83 - 您不必将控件放在 Dockerfile 中。 您可以将“--cap-add”选项(或类似选项)添加到“docker build”命令中。 如果我们遵循您的逻辑,shell 脚本不应允许使用“sudo”命令,因为有人可能会编写做坏事的脚本。

但是,您不会将 sudo 交给您不完全信任王国钥匙的人。
Build 必须能够尽可能安全地运行不受信任的代码。

引入 CLI 标志以在构建时启用额外功能破坏了构建的可移植性,这就是尚未添加它的原因。

也就是说,安装程序在这里请求它本身不应该访问的东西几乎肯定是错误的。

确切地。 你不应该给你不信任的人运行需要特权的 docker 构建的能力,但 docker 不应该阻止你_做_信任的人这样做。 这是一个政策决定,当工具假定为我做出政策决定时,我真的很不喜欢它。 一个好的工具可以让我以一种清晰而不令人惊讶的方式实施我所做的政策决定。

你没有看到更大的图景。

这个生态系统不仅仅是你的服务器和我的服务器。 例如,DockerHub 一直在构建不受信任的代码。

那么 DockerHub 绝对应该_不_启用为其构建添加功能。 如果这意味着我无法将我的 docker 构建推送到 DockerHub,我可以接受。

@cpuguy83 @tianon @jpetazzo -- 当 FUD 开始时,我不得不

允许这些事情会损害整个 DockerHub

srsly?
实现这个功能 == TEOTWAWKI ?

当然,DockerHub 永远不会使用请求的--privileged标志运行docker build
不用多想,至少有两种明显的实现方式:

  • 标志仅在您还使用一些新标志启动docker -d时才有效,例如: --i-want-a-broken-security-model
  • 创建启用代码路径的编译时标志。

总的来说,咬牙切齿的比率与基于工程的原因反对实施的比例在这里似乎非常高。

@tamsky然后我们有一种情况,构建工作在一个地方而不是另一个地方。
我正在解释为什么事情是这样的,而不是争论一个或另一个。

但也......大多数东西不需要任何特权访问,而那些确实需要特权访问的东西通常_真的_不需要它来安装工作。 如果某些东西的安装因此失败,则该安装程序已损坏,例如引用的 tomcat 问题就是这种情况。
启用这样的功能会鼓励人们以特权模式运行,而不是真正解决手头的真正问题。

@cpuguy83

然后我们会遇到这样一种情况,即构建在一个地方工作但在另一个地方无效。

请想象一下,我们被神奇地传送到了一个 _policy_ 不同的世界,有些构建在一个地方工作但不在另一个地方......

为什么这是一件大事?
究竟谁在乎?

Docker Inc 是否考虑过“所有构建必须在任何地方工作”的最低公分母口头禅/要求实际上可能忽略了实际的客户需求?

目前的政策是将客户的工程成本外部化,以“让 X 在 docker 中构建”:

您不是在 docker 中提供此功能,而是强制世界上每个“不需要任何特权访问”(但实际上确实需要)的第 3 方项目首先进行更新或猴子修补以处理 docker 构建案例。

最终,如果 Docker 将在多个平台上运行,“docker build”将不会在所有系统上都以相同的方式运行。 也就是说,Windows 容器、Solaris 容器甚至 ARM Linux 容器的构建将与 x86-64 Linux 上的不同。 这些的安全上下文也会有所不同,具体取决于它们的平台。

这就是说, @cpuguy83 ,我们不能总是假设 Dockerfiles 会保持通用。 但是,我同意我们需要尽量减少它们之间的差异。 在最终需要围绕多架构/多平台支持进行的对话中,可能值得考虑需要此功能的用户,尽管它很危险。

构建并非在任何地方都有效,因为例如加载的应用程序装甲配置文件。
另外,您将如何处理烘焙到图像中的预缓存 docker 容器?

第18 11. 2014年,在2:53,tamsky [email protected]写道:

@cpuguy83

然后我们会遇到这样一种情况,即构建在一个地方工作但在另一个地方无效。

请想象一下,我们被神奇地传送到了一个政策不同的世界,有些建筑在一个地方工作,但不在另一个地方......

为什么这是一件大事?
究竟谁在乎?

Docker Inc 是否考虑过“所有构建必须在任何地方工作”的最低公分母口头禅/要求实际上可能忽略了实际的客户需求?

目前的政策是将客户的工程成本外部化,以“让 X 在 docker 中构建”:

您不是在 docker 中提供此功能,而是强制世界上每个“不需要任何特权访问”(但实际上确实需要)的第 3 方项目首先进行更新或猴子修补以处理 docker 构建案例。


直接回复此邮件或在 GitHub 上查看。

在这种情况下,“损坏”的不是“安装程序”,而是 Tomcat 7。我使用的是 Bitnami 的 Tomcat 堆栈,它将 Tomcat 与 Apache 和 MySQL 集成在一起。 Docker 位于源、配置、集成、测试和打包服务供应链的末端。 要求我“修复”Tomcat 使我无法利用此供应链。 手动构建我想要的映像(使用“--privileged”启动容器,运行安装程序,对容器进行快照等)比“修复”Tomcat 容易得多。

+1
我无法将我的厨师角色移植到 docker,因为它们都涉及使用 ufw 来打开端口。
添加 --privileged 来构建可以解决这个问题。

+1。 不能将 debootstrap 作为我的 Dockerfile 中的一个步骤。

+1。 不能将 debootstrap 作为我的 Dockerfile 中的一个步骤。

通过 Dockerfile / build 构建我的 chroot 似乎很自然,但遇到了与@fbrusch提到的相同的问题。

FROM ubuntu:utopic
ENV HOME /root
RUN sudo apt-get update
RUN sudo apt-get install -y eatmydata
RUN for i in /usr/bin/apt*; do sudo ln -s /usr/bin/eatmydata $(basename $i); done
RUN sudo apt-get install -y debootstrap qemu-user-static binfmt-support
RUN sudo debootstrap --foreign --arch arm64 trusty ubuntu-arm64-chroot
RUN ls ubuntu-arm64-chroot
RUN sudo cp /usr/bin/qemu-aarch64-static ubuntu-arm64-chroot/usr/bin
RUN sudo cp /etc/resolv.conf ubuntu-arm64-chroot/etc
RUN sudo DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ubuntu-arm64-chroot /debootstrap/debootstrap --second-stage; sudo cat ubuntu-arm64-chroot/debootstrap/debootstrap.log

失败:

Step 11 : RUN sudo DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ubuntu-arm64-chroot /debootstrap/debootstrap --second-stage; sudo cat ubuntu-arm64-chroot/debootstrap/debootstrap.log
 ---> Running in 2654257e860a
I: Keyring file not available at /usr/share/keyrings/ubuntu-archive-keyring.gpg; switching to https mirror https://mirrors.kernel.org/debian
W: Failure trying to run:  mount -t proc proc /proc
W: See //debootstrap/debootstrap.log for details
gpgv: Signature made Thu May  8 14:20:33 2014 UTC using DSA key ID 437D05B5
gpgv: Good signature from "Ubuntu Archive Automatic Signing Key <[email protected]>"
gpgv: Signature made Thu May  8 14:20:33 2014 UTC using RSA key ID C0B21F32
gpgv: Good signature from "Ubuntu Archive Automatic Signing Key (2012) <[email protected]>"
mount: block device proc is write-protected, mounting read-only
mount: cannot mount block device proc read-only
 ---> de534a4e5458
Removing intermediate container 2654257e860a
Successfully built de534a4e5458

除了RUNP ,还有一个构建标志--insecure
对于所有 RUN 命令,后续容器将使用--add-cap=all 。 这不是特权,因为特权也做其他一些事情......
但实际上,如果在某些时候需要,这可以更改以实现完整的privileged设置,而无需修改标志。

@cpuguy83
我不介意必须使用传递到 docker build 的标志来使 RUN 命令获得特权或启用 RUNP 命令。 能够查看 Dockerfile 并通过命令或其中的某些内容告诉它需要特权访问是有价值的,并且在运行时而不是进入第 10 步并出错,它会在 Dockerfile 开始时使用快捷方式包含需要特权的命令。


将我带到这个线程的用例是绑定安装,我希望能够在容器内进行。 现在,只有在特权模式下运行容器才能执行这些操作。 它强制您在启动时将命令链接在一起,或者有一个 init 脚本运行以在您想要运行的进程之前完成系统设置。

能够在 Dockerfile 中包含以下内容会很好:

RUN mount --bind /dir1 /dir2

我将更多地描述我的用例,所以这不仅仅是一个广泛的给我特权命令的请求。 我的特殊情况是我想将应用程序区域中的安装目录绑定到附加的数据卷。

例如

/usr/local/application/data -> /mnt/data 
/mnt/data -> HOST:/var/datasets/dataset1

这也可以通过将卷直接装入应用程序区域来解决,但我正在寻找一种方法将它们提供在公共位置并让应用程序容器执行其特定映射。 这也可以通过 symlinks 解决,但一些应用程序不能很好地使用符号链接作为它们的目标/数据文件夹。 如果应用程序支持配置其数据目录位置,也可以指向卷安装区域。 我的用例是应用程序不支持配置数据目录位置,现实情况是总会有应用程序必须执行一些绑定安装或符号链接以正确分离它们的数据和应用程序空间。

这种能够做到这一点的能力 A -> B -> C 允许保持数据容器的通用性,并为您可以使用--volumes-from与应用程序和数据容器实现的不同组合提供灵活性。

您也可以通过使用带有--volumes-from的容器链来实现这一点:

GenericDataContainer -> ApplicationDataContainer -> ApplicationContainer

这可能是正确的答案,但如果应用程序容器可以执行绑定安装,您就不必再为应用程序数据创建另一个容器。

我今天可以通过在特权模式下运行容器然后执行挂载绑定来实现这一点,但是正如您将在下面看到的,没有办法使挂载绑定持久化,并且每次启动容器时都必须重置它. 符号链接在提交时保留。

我的特定用例的答案可能是使用 3 链容器方法或 init 脚本,但是能够从 Dockerfile 执行绑定装载容器内(或其他特权命令)会很好。 可能还有其他可以描述的绑定安装用例,它们不涉及任何主机到容器的映射,这些映射无法通过链接数据容器来解决。

不确定这是否与绑定挂载特定问题相关或更多,但是当您执行 docker commit 时特权命令的结果仍然存在将允许您将 docker 镜像的构建和 docker 镜像的运行分开。 您可以控制执行 docker build 的区域,最终用户只能获得他们可以在非特权模式下运行的已提交容器。 当您执行绑定安装和提交时,这目前不是原因。 不过,这可能与/proc/mounts工作方式更相关。

这是一个简单的例子

[root@ip-10-0-3-202 ~]# docker run --privileged -i -t --name test_priv centos:centos6 /bin/bash
[root<strong i="17">@d1d037cb170c</strong> /]# cat /proc/mounts 
rootfs / rootfs rw 0 0
/dev/mapper/docker-202:1-25352538-d1d037cb170c12dab94ebd01c56807210cf2aec50bef52c944f89225c8346827 / ext4 rw,seclabel,relatime,discard,stripe=16,data=ordered 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,mode=755 0 0
shm /dev/shm tmpfs rw,seclabel,nosuid,nodev,noexec,relatime,size=65536k 0 0
devpts /dev/pts devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0
sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
/dev/xvda1 /etc/resolv.conf xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hostname xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hosts xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
tmpfs /run/secrets tmpfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
devpts /dev/console devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0

创建一个绑定挂载示例,同时创建一个符号链接示例

[root<strong i="6">@d1d037cb170c</strong> /]# mkdir /var/data1
[root<strong i="7">@d1d037cb170c</strong> /]# mkdir /var/data2
[root<strong i="8">@d1d037cb170c</strong> /]# mount --bind /var/data1 /var/data2
[root<strong i="9">@d1d037cb170c</strong> /]# ln -s /var/data1 /var/data3

从所有 3 个目录都可以看到显示文件

[root<strong i="13">@d1d037cb170c</strong> /]# touch /var/data1/test
[root<strong i="14">@d1d037cb170c</strong> /]# ls /var/data1
test
[root<strong i="15">@d1d037cb170c</strong> /]# ls /var/data2
test
[root<strong i="16">@d1d037cb170c</strong> /]# ls /var/data3
test

显示/proc/mounts已更新

[root<strong i="21">@d1d037cb170c</strong> /]# cat /proc/mounts
rootfs / rootfs rw 0 0
/dev/mapper/docker-202:1-25352538-d1d037cb170c12dab94ebd01c56807210cf2aec50bef52c944f89225c8346827 / ext4 rw,seclabel,relatime,discard,stripe=16,data=ordered 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,mode=755 0 0
shm /dev/shm tmpfs rw,seclabel,nosuid,nodev,noexec,relatime,size=65536k 0 0
devpts /dev/pts devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0
sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
/dev/xvda1 /etc/resolv.conf xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hostname xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hosts xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
tmpfs /run/secrets tmpfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
devpts /dev/console devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
/dev/mapper/docker-202:1-25352538-d1d037cb170c12dab94ebd01c56807210cf2aec50bef52c944f89225c8346827 /var/data2 ext4 rw,seclabel,relatime,discard,stripe=16,data=ordered 0 0

退出停止它的容器,然后重新启动

[root<strong i="25">@d1d037cb170c</strong> /]# exit
[root@ip-10-0-3-202 ~]# docker start -a -i test_priv
test_priv

/proc/mounts缺少绑定安装

[root<strong i="7">@d1d037cb170c</strong> /]# cat /proc/mounts 
rootfs / rootfs rw 0 0
/dev/mapper/docker-202:1-25352538-d1d037cb170c12dab94ebd01c56807210cf2aec50bef52c944f89225c8346827 / ext4 rw,seclabel,relatime,discard,stripe=16,data=ordered 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,mode=755 0 0
shm /dev/shm tmpfs rw,seclabel,nosuid,nodev,noexec,relatime,size=65536k 0 0
devpts /dev/pts devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0
sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
/dev/xvda1 /etc/resolv.conf xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hostname xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hosts xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
tmpfs /run/secrets tmpfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
devpts /dev/console devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0

符号链接幸存下来,但没有绑定安装

[root<strong i="11">@d1d037cb170c</strong> /]# ls /var/data1
test
[root<strong i="12">@d1d037cb170c</strong> /]# ls /var/data2
[root<strong i="13">@d1d037cb170c</strong> /]# ls /var/data3
test
[root<strong i="14">@d1d037cb170c</strong> /]#

重置绑定挂载

[root<strong i="18">@d1d037cb170c</strong> /]# mount --bind /var/data1 /var/data2

不是退出容器,而是使用ctrl+p ctrl+q ,然后提交容器

将容器作为新镜像提交,以非私有模式从镜像启动新容器

[root@ip-10-0-3-202 ~]# docker commit test_priv test_priv
74305f12076a8a6a78f492fd5f5110b251a1d361e63dda2b167848f59e3799e2
[root@ip-10-0-3-202 ~]# docker run -i -t --name test_nonpriv test_priv /bin/bash

检查/proc/mounts
绑定挂载丢失,不确定是什么触发了额外的 /proc/[sys,sysrq-trigger,irq,bus,kcore] 挂载

[root<strong i="5">@ba1ba4083763</strong> /]# cat /proc/mounts 
rootfs / rootfs rw 0 0
/dev/mapper/docker-202:1-25352538-ba1ba40837632c3900e4986b78d234aefbe678a5ad7e675dbab7d91a9a68469e / ext4 rw,context="system_u:object_r:svirt_sandbox_file_t:s0:c327,c505",relatime,discard,stripe=16,data=ordered 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev tmpfs rw,context="system_u:object_r:svirt_sandbox_file_t:s0:c327,c505",nosuid,mode=755 0 0
shm /dev/shm tmpfs rw,context="system_u:object_r:svirt_sandbox_file_t:s0:c327,c505",nosuid,nodev,noexec,relatime,size=65536k 0 0
devpts /dev/pts devpts rw,context="system_u:object_r:svirt_sandbox_file_t:s0:c327,c505",nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0
sysfs /sys sysfs ro,seclabel,nosuid,nodev,noexec,relatime 0 0
/dev/xvda1 /etc/resolv.conf xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hostname xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
/dev/xvda1 /etc/hosts xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
tmpfs /run/secrets tmpfs rw,context="system_u:object_r:svirt_sandbox_file_t:s0:c327,c505",nosuid,nodev,noexec,relatime 0 0
devpts /dev/console devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
proc /proc/sys proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/sysrq-trigger proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/irq proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/bus proc ro,nosuid,nodev,noexec,relatime 0 0
tmpfs /proc/kcore tmpfs rw,context="system_u:object_r:svirt_sandbox_file_t:s0:c327,c505",nosuid,mode=755 0 0

符号链接幸存下来

[root<strong i="9">@ba1ba4083763</strong> /]# ls /var/data1
test
[root<strong i="10">@ba1ba4083763</strong> /]# ls /var/data2
[root<strong i="11">@ba1ba4083763</strong> /]# ls /var/data3
test
[root<strong i="12">@ba1ba4083763</strong> /]# exit

我目前正在尝试使用dind在我的构建步骤中运行

每个人,如果你想要这个,试试'/usr/bin/unshare -f -m -u -i -n -p -U -r -- /path/to/binary'。 这将在您的构建中创建一个具有用户命名空间的容器。 您可以根据需要调整选项以取消共享。 我实际上使用它来运行“/sbin/capsh”,以精细地设置我的进程的功能。

我不能说这将解决特权构建的所有用户案例,但它应该对你们中的一些人有所帮助。

我同意这应该成为 Docker 本身的一部分,并且用户命名空间的集成似乎正在进行中。

@saulshanabrook你不能在构建中运行

对于希望运行 docker 镜像的人来说,这不是一个真正的解决方案,但我会注意到 'unshare' 和 'capsh' 确实有效,因此可以在非特权容器中执行类似容器的运行时(例如在构建期间) )。 可以说,可以绕过“docker run”并手动执行此步骤,然后将图像重新提交回 docker。 我今天有大部分工作,即使我没有把它全部包在一个蝴蝶结里。 当然,最终这些功能需要进入 Docker 本身。

+1 用于通过 RUNP 的 docker pull

无法运行 docker build 特权促进了使用 shell 和 docker commit 手动构建,这使得 Dockerfiles 毫无意义。 我不认为向 docker build 添加特权标志会在构建和特权构建之间划清界限; 当标志被添加到运行时已经绘制了这条线并且需要支持它。

+1 这使得在任何给定时间点都可以重现 docker 容器(只需要单独携带 dockerfile)

+1 不得不完全分解我的 ansible 基线角色才能解决这样的问题。 我真的希望 docker 采用能让我使用大量现有的 ansible 代码,但不仅我已经为大小创建了自定义角色,而且现在我不得不解决这样的问题。

@lsjommer你需要解决哪些问题? --privileged 是一种完全不安全的容器运行方式,它为容器中的用户提供对主机的完全根访问权限。

我不是说我们不要实施这个,但让我们真正了解我们在谈论什么。

此外,如果有人想要这样做,这将相对容易实现......

@cpuguy83这是来自我们标准的“裸机”基线角色,我试图将其引入 docker 容器以安装所有库,并且它处理共享内存,但也许我什至不需要在容器构建中打扰它并且只需要在容器主机上运行它?
http://pastebin.com/P3QQxjNQ

我承认我并不完全了解Docker如何处理资源共享。

@ljsommer所以设置 shm 是一个不同的野兽,无论如何都不会在 RUN 命令之间持续(或者当你实际上docker run )。

@cpuguy83是的,我认为这主要是我的错,因为我遇到了我认为的问题,我可以转移到容器主机本身的基线上。
感谢您花时间做出回应,并为在抱怨之前没有适当地教育自己而道歉。
;)

在构建过程中对 RUNP / -privileged 有任何想法吗?
设置 ip 表以限制 docker 访问特定的 ip 地址会很棒

我还想要 RUNP 和/或“docker build --privileged”。

FROM ubuntu:latest
MAINTAINER xyz

RUN apt-get -qq update
RUN apt-get -yq install iptables

RUN iptables -t nat -I OUTPUT -p tcp --dport 443 -j DNAT --to-destination 127.0.0.1:8080 && iptables-save > /etc/iptables.rules

由于以下错误,此 Dockerfile 不起作用,但如果使用“docker run --privileged”则起作用...

getsockopt failed strangely: Operation not permitted

@malcm , @sakurai-youhei: 即使你有RUNP ,它在这种情况下也不起作用,因为 iptables 规则不会持久存在于文件系统中。

让我解释一下:当你执行RUN x ,Docker 会执行x然后获取文件系统的快照。 文件系统之外的东西(运行进程、路由表、iptables 规则、sysctl 设置...)不存储在 Docker 镜像中。

如果您想要自定义 iptables 规则,一种方法是:

  • 例如用--name myapp启动你的容器
  • 启动另一个容器,特权,一次性,以设置 iptables 规则,例如docker run --net container:myapp --privileged iptablesimage iptables -t nat ...

那有意义吗?

@jpetazzo :感谢您的回复。 就我而言,我将第二个命令用于使 iptables 规则作为文件系统上的数据持久化,如下所示。 这应该使我能够在使用 --privileged 选项启动容器后加载 iptables 规则。

RUN do-something-with-iptables && iptables-save > /etc/iptables.rules

没有 RUNP 也没有“build --privileged”,我被迫这样写:

ADD iptables.rules /etc/

是的,这可能就足够了,但是,我需要在我的存储库中的 Dockerfile 旁边添加 iptables.rules。

这就是为什么我想要(或想要温和地)RUNP。 :)

@jpetazzo @strib
除了 iptables 问题、挂载和其他特权操作之外,我认为我们应该解决一个构建场景。

我们提供用于在 VM 中部署和裸机安装的设备。 但是,为了测试,我们使用容器环境。 反过来,在这些设备内部,我们运行容器。 所以测试容器必须基于docker-in-docker。 现在假设我们有一个需要在测试镜像中预加载的服务镜像(这样在测试时就不会从注册中心下载服务镜像)。 现在我们不能这样做,因为在构建使用 d-in-d 作为基础的 Dockerfile 期间,我们无法以特权模式运行 d-in-d 容器:docker daemon 不会启动,“docker pull " 或 "docker load" 将不起作用。

我遇到了一个问题,在 RHEL7 主机上运行时,如果当前用户是 root 用户, su会失败。 奇怪的是,如果当前用户是其他用户, su工作正常。 无论如何,解决方法是将 run 命令传递给标志--add-cap=SYS_RESOURCE ; 然而,由于这个问题,在构建步骤中无法做到这一点。

+1 使用docker rundocker commit围绕 Dockerfile 编写脚本是荒谬的。 请包含此功能。

+1 关于此功能的必要性。 我认为可以在配置文件中配置全局“安全级别”,这会限制可以提供给容器的功能。 应该有一个安全的默认值(就像今天一样),系统管理员可以更改它以允许容器以更多权限运行。 具有此类 RUNP 指令的 dockerfiles 可能无法在具有此类全局限制的系统上运行并显示诸如“此 Dockerfile 需要以下功能......才能构建”之类的消息。

我认为这可以在安全性和可用性之间取得平衡。

我们在尝试使用 evli 专有数据库构建映像时也遇到了这个问题,该数据库在其中应保持无名。
数据库想要分配大量内存,这是 docker 不允许的。

我们当前的解决方法是一个 2 阶段构建,包含一个 run --privileged 步骤和单独的提交步骤。

也许我们可以配置 docker 以允许以其他方式分配内存。 由于它是专有的,因此很难找出 db 实际想要做什么。

+1
对于此功能。
有关历史和用例示例,请参阅此欺骗
https://github.com/docker/docker/issues/12138#issuecomment -90536998
感谢@cpuguy83指出

我也有这个问题,除非提供了特权标志,否则不允许在 docker build 期间尝试挂接到 cifs 共享,有什么办法解决这个问题吗?

现在有一个实现这一点的拉取请求; 你可以在那里查看进度; https://github.com/docker/docker/issues/12261

如果某些东西确实需要特权模式,那么它可能会以某种方式修改主机,这意味着该映像可能不可移植,因为这些修改需要在尝试使用该映像的其他主机上运行。

一旦#13171 被合并,我认为我们应该关闭它,因为它会使你自己的构建器变得微不足道,因此允许 --privileged。
我不认为内置的docker build应该允许这样做。

所以@cpuguy83 ,如果我理解正确的话,支持这个问题的方法是完全重新实现docker build但有一个额外的参数?

我想是说,一旦其他补丁通过,我需要将我自己的docker build (也许docker pbuild ?)放在一起来填充附加功能?

这个问题有什么进展吗? 我检查了上面提到的 PR,它们都失败了。
是否可以将BUILD --privileged/--granted选项设置得更细化,并使对特定主机资源组的访问权限仅限于映像生成器/所有者?

+1 对于任何允许我在 Dockerfile 中执行RUN docker pull的解决方案。

用例:我需要一堆用于图像转换和文档构建的工具,但是,由于库冲突,无法将所有这些工具安装到单个图像中。 这就是为什么我将这些工具中的一些分离到一个单独的图像中,并且我想将所有工具分布在一个图像中,即图像中的图像。 这就是我想在我的 Dockerfile 中执行RUN docker pull的原因。

@cpuguy83看起来这个问题没有得到任何人满意的解决。 我绝对 100% 需要能够做一些像在构建期间写入/proc/sys/kernel/core_pattern一样乏味的事情。

在当前世界中,我可以通过run解决方法执行此特权操作,并且无论如何只需将该图像推送到集线器。 此外,我 _ever_ 生产的任何Dockerfile都不是严格可复制的,因为它们是从随机不断变化的公共存储库中提取的。 我不知道

  1. 我的图像的公众消费是一个优先事项。
  2. 他们有任何需要,永远,是可复制的。

人们正在_去_做一些糟糕的变通方法来在构建中获得privileged 。 我认为你绝对应该去你的用户所在的地方,并在核心构建工具中允许这样做。 如有必要,添加一条可怕的消息。

cc @thaJeztah ,他似乎对这个职位表示同情

看,我创建了一个 PR 来启用它,但它被拒绝了。
我没有看到任何形式的构建器会发生这种情况。

看起来你做了最后的决定。 那么我会在公关线程本身中激动。

这是在 CentOS 下安装较旧的 JDK 1.6 软件包所必需的,因为其 RPM 尝试注册的是 binmft_misc,它在未在 --privileged 下运行时失败。

Dockerbuild 是使用它构建容器的非国家机构。

复制

来自 Centos5.11
运行 yum intall -y jre-1.6.0_29-fcs

我们需要将构建的特权命令部分作为可选标志。 我正在尝试将我们的应用程序之一作为 POC 移植到 docker,但它对于我们的一个组件失败,因为它具有未应用的 IPtables 设置并且构建失败。 我可以手动进行必要的更改并提交它,但是 docker build 的乐趣是什么? 它只是构建的一部分,应该很容易移植,因为它已经是主要版本的一部分。

Docker 应该能够轻松地运行具有特权选项集的中间容器。

@shubhamrajvanshi我们正在将“构建器”移出守护进程(并移至客户端),这将为构建过程的更多自定义打开大门(包括能够实现自定义构建器)。 可以考虑允许“特权”构建,但这是重构后可以做出的决定。 (见 https://github.com/docker/docker/blob/master/ROADMAP.md#122-builder)

@shubhamrajvanshi你不能在构建中对 iptables 进行更改是有充分理由的,设置永远不会坚持。

使用 --privileged 可以做的事情很少,甚至在构建中也有意义。

@thaJeztah谢谢,这会有所帮助。
@cpuguy83即使我在图像上使用 iptables-persistent 包,情况也会如此。

不幸的是,这会将规则保存到磁盘,然后它们仍然需要重新加载。

_用户投票_

_在此讨论中有更改时获得通知的最佳方式是单击右上角的订阅按钮。_

下面列出的人通过随机 +1 对您有意义的讨论表示赞赏:

@karelstriegel

我也很喜欢这个,允许在 CoreOS 上使用 Docker 的 nVidia CUDA 驱动程序。 他们提供的安装程序根据内核源代码构建内核模块,然后使用 modprobe 安装它。 如果没有某种 --privileged 选项来构建,我无法看到如何使其工作。

为什么默认情况下不总是在构建时支持特权模式?

+1
我想在centos7的Dockerfile中使用mysql命令。
当然我们可以使用 entrypoint.sh 但如果我们可以使用 -privileged 来构建和运行它会更有用。

不需要 --privileged 来运行 MySQL 命令。

这个问题应该关闭,因为这似乎不会发生(甚至不应该发生)。
在构建中允许特权意味着允许构建器更改主机上的内容,这反过来又使图像仅适用于该主机(或具有类似修改的主机)。

在构建中允许特权意味着允许构建器更改主机上的内容,这反过来又使图像仅适用于该主机(或具有类似修改的主机)。

这是否适用于 chroot 用户案例?

我正在尝试弄清楚如何在没有这样的情况下执行dpkg-depcheck -d ./configure

在构建(或在没有 --priviledged 的​​情况下运行)期间,我收到以下错误 - 我不知道如何确定它需要什么权限或如何启用它。

dpkg-depcheck -d ./configure
strace: test_ptrace_setoptions_followfork: PTRACE_TRACEME doesn't work: Permission denied
strace: test_ptrace_setoptions_followfork: unexpected exit status 1
Running strace failed (command line:
strace -e trace=open,execve -f -q -o /tmp/depchJNii2o ./configure
devel<strong i="8">@98013910108c</strong>:~/src/cairo-1.14.2$ 

在大约 3 年和 162 条评论之后,我认为它有足够的兴趣去做。 关于大多数引用案例不需要特权模式的评论是正确的,即使是我自己的; 但不应用于禁止可能对本地、临时、探索性和/或应急构建有用的内容。 发布警告直到奶牛放出和谐,打印出命令行警告,辱骂和谴责它的使用,但给人们灵活性。 便携性并不总是每个人的主要兴趣。

_用户投票_

_获得更新通知的最佳方式是使用此页面上的_订阅_按钮。_

请不要对问题使用“+1”或“我也有这个”评论。 我们自动
收集这些评论以保持主题简短。

下面列出的人通过留下 +1 评论对该问题进行了投票:

@robeferre

+1

我真的需要在 docker 容器中安装 NFS 卷,直到现在我无法在没有“--privileged=true”标志的情况下创建 NFS 共享。 我认为最好的情况是使用特权命令构建映像。 这怎么可能?

+1

Step 19 : RUN lxc-create -t ubuntu.sf -n percise -- -r precise -a i386 -b root
 ---> Running in 4c51b7cf0058
lxc_container: lxccontainer.c: create_run_template: 893 error unsharing mounts
lxc_container: lxccontainer.c: create_run_template: 1084 container creation template for percise failed
lxc_container: lxc_create.c: main: 274 Error creating container percise
The command '/bin/sh -c lxc-create -t ubuntu.sf -n percise -- -r precise -a i386 -b root' returned a non-zero code: 1

我试图在构建期间在 docker 的 gentoo 系统中安装 gobject-introspection 但它失败并出现以下错误:

  • ISE:_do_ptrace: ptrace(PTRACE_TRACEME, ..., 0x0000000000000000, 0x0000000000000000): 不允许操作

当我尝试在容器中手动安装它时的结果相同,但是当从以特权模式启动的容器中尝试时(docker run --privileged),它运行良好。

当我尝试安装 glibc 时出现同样的问题。

所以我还需要一种如何在构建期间运行特权命令的方法。

我使用的是 docker 1.10.1 版,但 glibc 的问题没有出现在 1.9 版中

在 1.10 版本中,我们无法构建 32 位容器,因为网络不可用
--privileged 或 --security-opt seccomp:unconfined for BUILD - 真的很有必要。
或者 Dockerfile 中的相应指令

来自我的大 +1

在构建过程中无法使用“mount”命令对我来说是一个真正的问题。
我试图克服在构建期间无法将主机目录安装到容器中的限制,因此我在主机上设置了 NFS 服务器并尝试安装 NFS 共享,只是为了发现这是不可能的,因为非特权模式。

在我的用例中,我需要在图像中安装一些东西,而无需将其复制到构建上下文中,并在安装之前添加它。

感觉就像我别无选择。

thaJeztah 于 3 月 10 日引用了此问题
升级到 1.10.2 后 LTTng 行为的回归 #20818 关闭

不,它没有关闭,我们正在使用 1.11.0-0~wily 并且在 32 位容器中,自 1.10.0 以来网络无法正常工作,但 1.9.x 运行良好。
只有 -privileged 可以帮助我们启动容器。 但是我们不能建立新的

我感到惊讶的是,尽管人们已经在这个线程中乞求了 2.5 年,而且鉴于人们已经提交了 PR 来实现此功能,但如此多的人显然需要的东西却没有实现。

同意@ctindel ,这个问题是我从docker迁移到

@ctindel这是我们还没有准备好实施或支持的东西。 实现本身相当简单(我什至自己实现了,所以我们可以讨论),这不是问题。

--privileged是一个坦克,在构建时允许它是危险的,并且极大地影响了图像的可移植性。

布莱恩,

如果您有解决办法,也请与我分享。 我会
感谢。

谢谢
舒巴姆·拉杰万西
669-300-8346

在周一年,2016年5月2日下午2:30,布莱恩·高夫[email protected]写道:

@ctindel https://github.com/ctindel这是我们还没有准备好的事情
实施或支持。 实现本身相当简单(我什至
自己实现的,所以我们可以讨论),这不是问题。

--privileged 是一个坦克,允许它进行构建是危险的,并且
极大地影响了图像的可移植性。


你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/1916#issuecomment -216369957

我不明白对便携性的影响。 构建时的特权操作如何影响可移植性? 我的意思是,在有或没有特权的情况下以各种方式创建不可移植的图像并不难,但是是否有某种方式使使用特权操作构建的图像一定是不可移植的?

我不相信每个容器都必须是便携式的。 有些容器是为了与社区共享而创建的,有些可能是为部署内部应用程序而创建的。

需要在特权模式下运行的应用程序的可移植性问题在于应用程序本身。

特权模式是让他们无需更改代码即可运行应用程序的最后手段。

我相信需要特权模式构建的图像构建器明白这样的容器可能也需要在特权模式下运行。

应该明确记录不鼓励在特权模式下构建,因为它可能会产生可移植性问题。

从 Outlook手机发送

在周一年,2016年5月2日,在下午2点53分-0700, “特雷弗·布莱克韦尔”< [email protected] [email protected] >中写道:

我不明白对便携性的影响。 构建时的特权操作如何影响可移植性? 我的意思是,在有或没有特权的情况下以各种方式创建不可移植的图像并不难,但是是否有某种方式使使用特权操作构建的图像一定是不可移植的?

您收到此消息是因为您订阅了此线程。
直接回复本邮件或在Gi tHub上查看

@tlbtlbtlb因为特权模式可让您完全访问主机。 也许我设置了一些简单的东西,比如 shmmax 或者更糟糕的东西。
我保证这些事情会在可用的第一天发生。

@davidl-zend“便携”并不意味着与社区分享。 这意味着从一台机器转移到另一台机器。

@ cpuguy83正如其他人所指出的,还有许多其他方法可以破坏图像的可移植性。 如果没有特权构建过程,您所做的一切就是迫使人们进行两步过程,要么部分从 Dockerfile 构建,然后手动更改容器并进行提交,要么部分从 Dockerfile 构建并完成第一次启动容器时的特权安装很糟糕,因为这意味着如果你正在做一些耗时的事情,第一次启动可能需要几分钟才能工作。

鉴于我在各种论坛上看到的评论,我敢打赌,很多人已经在这样做,以解决当今存在的 docker 限制。

一旦您的架构在许多其他方面破坏了图像的可移植性,那么反对这个特定的风车又有什么意义呢?

显然,您将不再能够让 docker hub 或 travis-ci 构建您的映像,但是需要使用特权模式构建它的人无论如何都会理解这一点。

@ctindel我很想看到一些图像可移植性被破坏的例子

在第一个容器启动时做这种事情是_完全_正确的方法。
这是一个运行时配置,它不应该出现在图像中。

@cpuguy83您是否在争论这样一个事实,即有人可以从 Dockerfile 进行部分构建,以特权模式启动容器,进行更多更改,然后进行 docker 提交? 这与在特权模式下进行构建有何不同? 因为这就是今天其他人正在做的事情。

我不是想变得暴躁,我只是说这是对人们以一种尴尬的方式工作的平台的严重限制。

例如,除非您在系统中具有某些功能,否则无法正确安装 3rd 方 debian 软件包(可能还有 RPM)。 安装 debian 包不是“运行时配置”,它是安装过程的一个可怕部分。

@ctindel我根本没有在争论这个。 不同之处在于支持行为。 如果没有区别,我们就不会进行这次讨论。

对我来说,我是一个同意的成年人,希望能够在一堆节点上滚动一个包堆栈图像。 当前使用 Dockerfile 构建炸弹,所以我必须作弊才能绕过 docker 限制。

@cpuguy83我仍然不清楚(我认为该线程中的其他人)不提供人们正在以其他方式解决的此选项究竟会获得什么。 无论如何,在添加提交选项的那一刻,您似乎争论的那种架构纯度(我没有更好的词来形容)已经消失了,所以我真的不明白它是否通过具有特权构建或通过特权容器中的 docker 提交的 Dockerfile。

除了一种方法是为人们提供一个可怕的 PITA,另一种方法非常好地插入当前使用 Dockerfile 构建的机制。

还有,你没有回答我的问题。 为什么您认为 3rd 方 debian 包(或 packstack)的简单安装是“运行时配置”?

@ctindel便携性。 能做不代表支持,把它包含在build ,方便大家做,就代表支持。
我们_将_被主机之间无法工作的图像问题淹没......这基本上打败了Docker的全部原因。

如果一个包甚至需要--privileged来安装,那么它应该用包来解决。 安装不应该需要--privileged ...如果确实需要它,那么这表明安装本身不可移植(需要在主机上更改内容)...我什至想看到 docker 可以在没有--privileged的容器中运行(请注意,这是可运行的,您可以随心所欲地安装它,而无需 --privileged)。

但是允许它通过 docker commit 完成意味着它也被支持!

我不明白,你让很多人绕过这个产品的限制,因为你担心有人会就某种不受支持的形象向你们个人抱怨?

你仍然没有回答我的问题,为什么安装包的行为(我什至没有在这里谈论配置它)是“运行时配置”的行为。 仅仅说“便携性”并不意味着什么。

docker 是否有特定于 x86_64 的内容? 最终不会有为特定 CPU 架构构建的 docker 镜像吗? 这不是也使它们不可移植吗? 我的意思是整个想法无论如何你总是能够获取任何 docker 镜像并在世界上的任何 docker 主机上运行它,而不管其他很多变量似乎是不可能的,所以我不明白推动的超强需求回到人们要求的这个特殊功能上。

顺便说一句,让我在这里感谢您的回复和持续参与。 许多其他 github 项目都忽略了问题线程!

我同意人们通过使用docker run --privilegeddocker commit来解决这个问题的观点。 到目前为止,我已经为两家公司制定了这样的解决方案。 人们会制作这样的图像,并且表现得好像这样做是一件可怕的事情是没有意义的。

见鬼,如果你非常害怕支持用--privileged构建的容器,那么就在文档中清楚地说明,这样人们就会完全意识到他们这样做是在自担风险。 虽然到目前为止我还没有看到任何负面影响。 但话说回来,我们还没有尝试在不同的发行版上运行容器。

@PerilousApricot究竟是什么导致了 packstack 的问题? 我们很乐意修复特定问题,或帮助上游修复它们,但不要认为仅添加--privileged完全不受限制地访问您的主机服务器是正确的方法。 我所知道的人们在何处提出特定构建问题的所有情况通常都可以修复,因为大多数事情实际上并不需要主机上的 root 访问权限才能进行构建。

@justincormack启动它自己的服务的 3rd 方包(即不能更改)的解决方案是什么,其中 init 脚本需要挂载 tmpfs 文件系统? 我的意思是即使现在忽略 --privileged 也无法在构建期间执行 --cap-add 或 --security-opt apparmor:unconfined (我不认为?)

@ctindel不应该尝试在安装时挂载 tmpfs。 如果它在运行时需要 tmpfs 那么很好,但在安装时它肯定是不正确的。

@cpuguy83您正在将架构和实现理念强加于

这就是整个讨论的重点,您强加了任意限制,使使用 docker 变得更加困难,因为对“做错了”的人的支持请求有一些哲学上的担忧。

这就像说操作系统不应该允许人们改变进程调度类,因为如果你做错了它会导致优先级倒置。 或者,没有人应该制作锤子,因为如果你用错了它可能会击中你的拇指。

正如多次说过的那样,docker 已经通过 commit 命令支持这一点,这对您的用户来说更加痛苦。 不想要这个功能的人不会使用它,想要通过理解限制来使用它的同意的成年人可以睁大眼睛这样做。

@ctindel更像是不,您无法处理这颗核弹,因为您可以杀死半径 50 公里内的所有人。

这个包在安装过程中需要加载 tmpfs 有什么用? 安装实际上是将文件从某种存档格式提取到 rootfs。

什么都可以改变。
在安装时不挂载 tmpfs 比在构建时启用特权更简单、更安全。

Docker 是关于工作负载的可移植性。 启用构建特权(或额外特权,或调整安全配置文件等)从根本上打破了这一点,这不是我们今天可以接受的。

commitbuild是两个非常不同的东西,仅仅因为可以以一种方式做某事并不意味着我们也应该允许以其他方式做这件事。

FROM python

ENV PACKSTACK_VERSION 7.0.1
RUN cd /opt && git clone https://github.com/openstack/packstack.git \
  && cd packstack \
  && git checkout $PACKSTACK_VERSION \
  && rm -rf .git \
  && python setup.py install

无需特权。

盈利的教会。
有一天,“强制”可移植性会扼杀这个项目——它已经在这样做了。
由于难以捉摸的可移植性,许多功能被拒绝,因此没有取得如此大的进步......
有一天,有人会 fork 一个项目并使可移植性成为可选。 梦想......梦想..​​....阿门。

如果我们把它分解为两种情况:

  1. 轻率地使用特权操作的安装程序,例如安装 tmpfs 以提高性能。 这样的安装程序可以很容易地修复(但可能不会在不久的将来)。

在这种情况下,Docker 抵制行为不佳的安装程序是一种有效的理念。 大多数安装程序都有某种解决方法,这只会使 Dockerfile 更长一点。

  1. 从根本上依赖特权操作的安装程序,例如为 GPU 驱动程序安装内核模块。 这些基本上也是不可移植的。 例如,它们不适用于 Mac 的 docker-machine。

在这种情况下,Docker 体验无论如何都被破坏了。 我无法在 Mac 上使用 docker-machine,例如,我只能在兼容的目标主机上构建映像。 我的用例是在主机操作系统 (CoreOS) 上安装 nVidia GPU 驱动程序,这不鼓励直接在主机操作系统中安装。

所以,我想我已经看到了在任何一种情况下都不支持 --privileged 的​​优点。 我认为让我改变主意的是使用 docker-machine 在我的笔记本电脑上构建图像的便利性,而不是首先将我的代码推送到 Ubuntu 机器并在那里构建。

@tlbtlbtlb我不明白你指的是什么“美德”。 考虑一些不无聊的事情,但是有大量的 docker 镜像可以在一个环境中运行,但不能在另一个环境中运行。 例如,您可以将主机卷挂载到 linux->linux 的 mongodb 容器中,因为 mmapv1 存储驱动程序可以正常工作,但是您无法通过 virtualbox 将 mac osx 目录传递到笔记本电脑上的 mongodb 容器,因为在这种情况下, mmap 的东西将无法正常工作。

我意识到这在构建方面不是问题,但是 docker 图像是“可移植的”并且可以“在任何地方运行”的想法在这一点上完全是无稽之谈。 如果他们不能在任何地方运行,那么说他们应该可以“在任何地方建造”有什么好处?

关键是 mongodb 图像无处不在。 提供无效的运行时配置是另一回事。

Docker 对可移植配置和非可移植配置进行了非常具体和直接的分离。

这个怎么样 ?
我需要将容器内的真实 ips 用于我的 nginx 配置检查通过。

这是我的 Dockerfile:

FROM ubuntu:14.04.4

RUN apt-get update
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:nginx/stable
RUN apt-get update
RUN apt-get install -y nginx-full vim
RUN ifconfig lo:0 192.168.168.70 netmask 255.255.255.0 up
RUN ifconfig lo:1 192.168.168.57 netmask 255.255.255.0 up
RUN ifconfig lo:2 192.168.168.58 netmask 255.255.255.0 up

ADD . /etc/nginx

➜  nginx git:(ha-node-01) ✗ docker build -t nginx4test .
Sending build context to Docker daemon 976.4 kB
Step 1 : FROM ubuntu:14.04.4
 ---> 90d5884b1ee0
Step 2 : RUN apt-get update
 ---> Using cache
 ---> eea42cb6135d
Step 3 : RUN apt-get install -y software-properties-common
 ---> Using cache
 ---> 9db86ab17850
Step 4 : RUN add-apt-repository ppa:nginx/stable
 ---> Using cache
 ---> 5ed2266a93a9
Step 5 : RUN apt-get update
 ---> Using cache
 ---> 09fcfdc1fed3
Step 6 : RUN apt-get install -y nginx-full vim
 ---> Using cache
 ---> cc0c1662e009
Step 7 : RUN ifconfig lo:0 192.168.168.70 netmask 255.255.255.0 up
 ---> Running in 5d962ec4e35d
SIOCSIFADDR: Operation not permitted
SIOCSIFFLAGS: Operation not permitted
SIOCSIFNETMASK: Operation not permitted
SIOCSIFFLAGS: Operation not permitted
The command '/bin/sh -c ifconfig lo:0 192.168.168.70 netmask 255.255.255.0 up' returned a non-zero code: 255

当然,如果我使用特权选项运行容器,我可以将 ip 设置为环回接口。 但它是一个需要添加的脚本。

@ cpuguy83我有大约20行左右iptable项我想RUN在我的Dockderfile ,但不能因为我需要--cap-add=NET_ADMIN 。 无论谁在运行容器,也不管他们在什么机器上运行(容器运行内部应用程序),这些命令都应该发生。 根据您上面的讨论,您会在哪里/如何建议我这样做?

@MatthewHerbst不幸的是,iptables 规则不会/不能保留图像。

@cpuguy83我正在使用centos:6图像并且可以运行 run /sbin/service iptables save将规则持久化到文件系统。 我相信他们通过iptables-persistent包在 Ubuntu 和其他人上具有类似的功能。

您可以为该文件生成 iptables 规则,无需
实际应用它们。 容器运行的网络情况可能
非常不同,所以你应该只在运行时应用规则(如果那样,你
主机生成它们可能会更好)。

2016 年 5 月 16 日 16:03,“Matthew Herbst”通知@ github.com 写道:

@cpuguy83我在 CentOS 上,可以运行 run /sbin/service iptables save to
将规则持久化到文件系统。 我相信他们是相似的
通过 iptables-persistent 包在 Ubuntu 和其他系统上提供功能。


你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看

@justincormack不知道为什么我没有想到这一点! 谢谢!

使用docker service时,您应该如何执行需要特权的命令? 我需要在我的几台机器上设置主机名,但不幸的是这需要特权。

@nostrebor与这个未解决的问题非常无关。
我们正在评估服务需要存在哪些选项,而不是一对一复制它们。 特权模式可能不会在 1.12 中用于服务。

我正在尝试 docker builds,它编译一些东西以供安装,但它必须针对存在于 CVMFS 网络文件系统上的库进行编译。 当然,我不能在不运行 --privileged 的​​情况下挂载 CVMFS,所以我根本无法使用 Dockerfile 来完成。

@cpuguy83 @tlbtlbtlb这是一个“安装程序”从根本上依赖于特权操作的情况。 但这不是我所说的“轻率使用”,我只需要访问网络文件系统上的共享库。 尽管如此,在这种情况下的安装并不是简单地从某个存档中提取文件。

我不明白如何挂载网络文件系统是一个可移植性问题。 (我们所有的目标环境都可以访问这个文件系统。他们必须这样做,因为他们构建了其他代码,这些代码也必须链接到网络文件系统上的二进制代码。)

我应该尝试不同的方法吗? 我应该在主机上挂载 CVMFS 并与容器或其他东西共享该目录吗? 我不想仅仅为了制作这个图像而设置一个外部构建系统——它所基于的图像已经有一个完整的构建系统来完成这项工作。 我只需要能够挂载 CVMFS。

我对使用 Dockerfile 执行此操作感到很兴奋,但似乎我将不得不使用带有docker run --privileged某些脚本以艰难的方式来完成它,或者使用其他东西而不是 docker。 有没有办法在没有特权访问的容器中挂载文件系统?

我做了一个变通方法,通过在脚本中放置/回显特权命令并使用 CMD 指令在容器入口点运行脚本,因此在构建这样的图像后,我能够在特权模式下运行容器并且一切正常。

@drstapletron ,根据 CERN cvmfs 文档,您现在有两个选择,要么将 cvmfs 从主机挂载到容器,要么在特权容器内安装 cvmfs。

对于秒的情况,我刚刚为 cmssw 人写了一个 docker 文件,在这里:
https://github.com/iahmad-khan/system-admin/blob/master/cvmfs-inside-docker.Dockerfile

所以使用这个文件,你可以只构建一个图像(或者你可以从 cmssw dockerhub 获取它),并在 P 模式下运行它,所有的东西都已经在容器内(ls /cvmfs/*)

不确定上面是否涵盖了这一点,因为它是有关此问题的相当长的反馈列表。 我也想拥有 --privileged 构建命令。 我当前的用例是解决我在 gentoo stage3 上构建 go ebuild 时遇到的问题。 如果我不使用容器,gentoo 手册中的当前说明会导致 systemd 在我 'umount -l /mnt/gentoo/dev{/shm,pts,} && umount -l /mnt/gentoo/{ proc,sys}' 来自使用 systemd 启动的系统......当我将我的 stage3 构建移动到 docker 容器中时,一切正常,直到构建需要 ptrace 或其他一些受限功能...... go-1.7.1。 ebuild 似乎需要。

现在我只是在 docker run 命令中运行构建,提交然后从那里继续,但最好在 docker build 命令本身中启用 ptrace 以避免手动步骤。

我也想要这个功能。 我想创建一个构建环境,但它需要一个内核模块,并且在我构建时 modprobe 不会与我合作。 有解决方法吗?

具体来说:

modprobe vcan && \
ip link add type vcan && \
ifconfig vcan0 up

似乎是一个完全合理的用例。

@seltzy我建议不要屏住呼吸等待docker任何人承认您的用例的合理性。

当谈到架构和功能包含时,他们非常严厉、务实、冷漠,并且往往会忽略任何和所有不适合_他们_路线图的用例。

我们普通人需要了解, docker团队做出的架构决策可以进一步满足他们自己(可能是商业客户和自助服务)的需求,而这些决策很少与我们(公共最终用户)非常费力地制定问题是我们这里的文件。

当然,他们可以通过这种方式自由分配工程资源。
但它确实提供了一个跟踪记录,如果该公司被描述为“认真对待用户的需求”,那将是令人难以置信的。

@tamsky

@tamsky我能理解您为什么会这么想,因为该项目没有接受您明确想要的功能。

我可以向你保证,这与任何类型的商业决策无关。 事实是,构建时的--privileged会产生不可移植的图像。
构建环境中的modprobe之类的东西没有帮助,甚至可能导致两个构建产生完全不同的结果。

我自己在构建时实现了--privileged 。 这不是一个工程问题,而且实现起来真的很简单。 它支持它,这就是问题所在。
对于高级用户,可以实现自定义构建器,甚至可以重用现有代码,使用可以包含特权支持的现有 API。

也就是说,这个问题仍然是有原因的。 那是因为人们在听。

感谢您的考虑。

@cpuguy83谢谢你的解释。 我没有意识到这是一个便携性问题。 我想我对此的渴望是由误解引起的。

当面临特权构建的诱惑时,一般的哲学方法是什么?

@seltzy不要太确定您的用例不是需要此功能的合理示例

@cpuguy83我仍在等待有关我的用例必须将其安装在我的容器中。 这需要容器以特权模式运行。 我所在的机构决定使用网络文件系统进行软件分发,这对于粒子物理学来说并不罕见。 您声称--privileged在构建时创建了不可移植的图像,但这与我的用例完全无关。 我们的开发模型已经放弃了由于使用网络文件系统(真的?)而可能会失去的任何可移植性。 我们只需要开发机器即将安装它。

@cpuguy83 PS 您提到了自定义构建器。 我在哪里可以找到这方面的信息? 谢谢!

无论如何,关于容器可移植性的整个讨论都是一个巨大的红鲱鱼。 您已经可以通过创建第 1 阶段映像、以特权模式启动容器、执行您必须执行的任何操作,然后使用 docker commit 从该容器创建最终映像来完成相同的操作。

一旦他们添加了 docker commit 选项,任何图像可移植性的概念就消失了,因此强迫人们分 3 步而不是 1 步来执行此操作并没有任何好处,只会惹恼那些真正可以使用特权构建选项的人。

@drstapletron挂载文件系统不一定会破坏可移植性(除非有人希望将其挂载在映像中)。
这里的问题是能够挂载文件系统也意味着能够做一些其他令人讨厌的事情。

@ctindel是的,您可以在您创建的容器中做任何您想做的事情。 事实上, docker build是构建图像的“支持”方法,这意味着我们需要确保使用它构建的图像_are_ 可移植。

便携式图像不是红鲱鱼。 工作负载可移植性是 Docker 的主要设计目标。 我们的主要指令,因为它是。

@seltzy大多数需要额外权限的东西都属于运行时,因为大多数时候提升的权限用于以某种方式修改主机。
也就是说,我当然可以理解在构建时需要一些东西(例如上面的 nfs 挂载)......但即使是 NFS 并手动构建映像(不是使用docker build ),我根本不会给容器--privileged或任何额外的功能,而是将 nfs 导出安装为一个卷。

@drstapletron mount不需要--privileged只需要一个更受限制的功能集,并且比完全特权模式更有可能发生得更快,因为这提供了对大多数人所做的主机的完全 root 访问权限不想。 (它仍然存在安全问题,但它们更易于管理)。

所以我有一个完全可移植的、非主机修改的用例。 它甚至是开源的,您可以在此处查看

基本上,我想在便携式 Docker 容器中运行 Mock 来构建自定义的 CentOS ISO 映像。 Mock,对于那些不知道的人,是一个容器化的 RPM 构建器。 问题是,因为它使用容器,所以我需要--privileged--cap-add 。 理想情况下,我认为docker build会像一个函数一样工作,接受一些参数并返回其最终结果。 但是,如果没有这些标志,我就无法做到这一点。

同样在这里 ! 因此,在 docker 中使用 mock 是一场噩梦:(

Sending build context to Docker daemon 9.728 kB
Step 1 : FROM centos
 ---> 980e0e4c79ec
Step 2 : MAINTAINER Gregory Boddin
 ---> Using cache
 ---> 93e709c87f25
Step 3 : RUN yum install -y spectool mock
 ---> Using cache
 ---> 7006ef8d0276
Step 4 : RUN useradd mock -g mock
 ---> Using cache
 ---> bfb931c56d89
Step 5 : ADD *.cfg /etc/mock/
 ---> Using cache
 ---> 15521d2822b1
Step 6 : RUN su mock -c"/usr/bin/mock -r edge-5-x86_64 --init"
 ---> Running in 542a742b6017
INFO: mock.py version 1.2.17 starting (python version = 2.7.5)...
Start: init plugins
INFO: selinux disabled
Finish: init plugins
Start: run
ERROR: Namespace unshare failed.

@cpuguy83写道:

事实是,--privileged on build 将屈服于不可移植的图像。

为什么不让--privileged用于那些不需要深远便携性的人?
官方文档中的一个简单注释将是一个合理的妥协(例如_警告:将--privilege传递给build命令可能会导致图像的可移植性较差!_)。 这几乎可以解决每个人的需求; 有些用户不需要便携性,有些用户需要,警告就足以满足每个人的需求。

我确信缺少build --privileged会使我当前的用例变得非常复杂。

它可以被称为--non-portable 。 我还没有使用 docker 的部署部分,但是如果没有它,隔离 + 覆盖文件系统的东西真的很有用。

我需要使用一些需要特权容器才能安装的专有软件。 对此我无能为力。 我坚持需要执行 3 阶段的构建、运行、提交过程。

容器可移植性对我或我的企业没有任何意义,事实上我敢打赌它对绝大多数企业没有任何意义。 重要的是我想维护更少的软件,所以我认为在这个问题上选择可移植性而不是可用性对Docker是不利的。

+1为此,在构建过程中我们使用setfacl,这在构建过程中失败并且服务无法在容器中启动。 我认为作为最终用户,我们不应该受到限制,只有在需要时才使用 --priviledge 选项并且默认值被禁用。

+1 为此。 在我们的构建过程中,需要挂载 /proc 和 /dev。 理想情况下,我们应该能够将挂载步骤作为 dockerfile 的一部分。

@samsun387为什么你的构建过程需要这个?

@skshandilya setfacl 不可移植,如果 acl 可以

@robhaswell “需要一个特权容器”并没有多大帮助。 安装时实际使用的是什么?

+1。 模拟 init 需要这个。
几乎阅读了整个问题。 不明白为什么人们连续 3 年一直问“你为什么需要这个”。

@Betriebsrat因为“X 需要这个”并没有那么有用。
“X”在做什么? 为什么“X”在构建阶段需要这个?

例如,上面具有挂载/proc/dev功能的情况似乎真的不是构建阶段的正确位置,甚至似乎图像会在这样的情况下绑定到主机一个案例。

“特权”也是坦克。 它绝对打开了一切,禁用了所有安全功能,提供了对通常只读位置的写访问权限……在那里某人可能只需要能够做非常具体的事情。

提出这些问题是为了让我们能够获得真正的用例以及我们如何满足这样的用例。

顺便说一句,当我说“安全功能”时,我的意思是两件事:

  1. 防止黑客入侵的措施
  2. 将应用程序问题与主机问题隔离开来(即,映像构建不应将映像与其构建的主机联系起来)。

看起来我的已经在 21051 之前解决了,我现在出去了:)

@shykes于 2013 年 11 月 28 日 @ https://github.com/docker/docker/pull/2839#issuecomment -29481246 ::

抱歉,当前的设计是强制执行“1 个源,1 个构建”,这就是为什么我们不允许 docker build 除了源目录之外的任何参数。

我了解某些构建目前无法进行的事实,因为它们需要特权操作。 为了正确处理这个问题,我们可能需要 1) 允许 Dockerfile 表达以特权方式构建的需求,以及 2) 实施授权/信任系统,允许 docker 暂停构建,正确警告用户风险,公开有关 Dockerfile 的来源和可信度的信息,然后收集用户允许或拒绝构建的决定。

@cpuguy83 ,设计是否从强制执行:“1 个源,1 个构建”发生了根本变化?
Docker 项目是否愿意更改该设计并允许此社区要求的功能?

上面 Shykes 的评论似乎阐明了“我们可能需要”做些什么来处理这个问题。 同时,所使用的语言(“可能”)似乎为 docker 项目提供了很大的空间来提出拒绝这种设计更改的其他理由。

添加 NEEDS_PRIVILEGED 声明是有道理的,但所有这些关于暂停构建的东西? 如果他们确实想要允许特权构建,则只是失败并显示错误并让操作员传递 --privileged 选项。

@cpuguy83问题是,在构建中需要特权模式的人通常是高级用户,他们非常清楚使用它的风险是什么。 他们中的大多数人接受了这一点,并通过简单地使用docker commit作为他们构建的一部分来解决这个问题。

你并没有以任何方式阻止人们在构建中使用特权模式,你只是让它变得烦人。

如果你的目标是让它变得烦人,那么就直接说出来并关闭这个问题,而不是让它持续多年。

说“我们不会修复此问题,因为我们希望这样做很烦人”并关闭此问题。

/线

@cpuguy83 ,根据我的理解,Mock 在创建其 chroot/容器环境时使用unshare(2)CLONE_NEWNS标志 - 可能还有其他标志。 这至少需要CAP_SYS_ADMIN

“X”在做什么? 为什么“X”在构建阶段需要这个?

在我们的用例中,我们不知道。 这是一些我们无法改变的专有废话。 问题是,我们的业务并不关心“安全性”(在这种情况下)或可移植性,或任何已列出的问题。 我们只是想把这该死的垃圾放在一个容器中,然后继续做一些有价值的事情。

正如@PonderingGrower所说,无论如何我们都会这样做,这只是我们在做这件事时浪费了多少时间的问题。

在构建中需要特权模式的人通常是高级用户,他们非常清楚使用它的风险是什么

我非常不同意这个假设。 总体而言,使用--privileged的人与盲目运行chmod -r 777的用户属于同一类别,“因为有人写道它解决了问题”

在我们的用例中,我们不知道。 这是一些我们无法改变的专有废话。 问题是,我们的业务并不关心“安全性”(在这种情况下)或可移植性,或任何已列出的问题。

“在这种情况下”,这里的意思是:在您的主机上提供“一些专有的废话”root 访问权限。

@thaJeztah

我们需要这个特性来在构建时使用 dind 来预配置我们正在构建的容器中的一些容器。

你在这里讨论了 3 年什么?

docker run有一个选项--cap-add--cap-drop等。 所以, RUN命令Dockerfile希望有相同的选项。 所以Dockerfile想要向父机器发送请求并要求它添加/删除一些权限。

父机器可以对这些请求做它想做的事情。 可以做shell交互,可以做gui确认对话框等,为什么在这个issue里讨论这些请求的解决?

大量 docker 用户希望能够在构建命令中使用 --cap-add 或 --privileged 来模拟运行命令中的内容。

这就是为什么这张票已经开放了 3 年,尽管维护人员对在这个特定实例中为用户提供他们想要的东西不感兴趣,但人们不断地参与其中。

@ctindel这绝对是这个问题的问题。 docker build --cap-addRUN --cap-add之间存在差距。

有些人只想用docker build --cap-add=caps_array解决来自子机器的权限请求。 它是什么? 这只是: caps_array.include? requested_cap

有些人想要pre_requested_caps.include? requested_cap 。 有些人想要stdout << requested_cap, stdin.gets == 'y'有些人想要gui_confirm requested_cap 。 有些人肯定会想要UAC_fullscreen_dialog requested_cap

requested_cap的解析方法取决于用户的口味,我认为这个问题永远不会被完成。

但是RUN --cap-add与人的口味无关。 我们还在等什么?

@andrew-aladev 我不太明白你的帖子在说什么。 关键是人们拥有不受他们控制的 3rd 方软件(RPM、DEB 等),他们希望在“docker build”时将其安装到映像中,并且需要额外的功能才能正确安装。 由于它们是第三方 RPM,因此无法在安装阶段解决增加权限的要求。

他们通过运行具有这些增强功能的容器,安装他们的软件,然后从该容器创建映像来解决这个问题。 这是一个痛苦,并清楚地表明没有功能性原因在构建时禁止添加上限,因为可以迂回地实现相同的目的。

@ctindel我的英语不是很好,抱歉。

我知道。 我试过出现 glibc 并且我收到了ptrace not permitted

docker可以单独运行具有增加/减少功能的容器。 RUN在命令Dockerfile应支持--cap-add--cap-drop

让我们想象一下我们的Dockerfile将有RUN --cap-add=SYS_PTRACE -- emerge -v1 glibc 。 它将如何运作?

  1. 子机器向父机器发送请求并请求SYS_PTRACE
  2. 父级允许扩展功能。
  3. 父级创建允许 SYS_PTRACE 的新容器。

我看到在这个问题上没有人真正在争论这个。 人们只是在争论一种允许这些能力的方法

@thaJeztah

总的来说,使用--privileged 的​​人都是盲目运行chmod -r 777 的同一类用户

这个人想要一种更灵活的验证所需功能的方法,而不仅仅是log :info, requested_cap; return privileged?

@ctindel你说

添加 NEEDS_PRIVILEGED 声明是有道理的,但所有这些关于暂停构建的东西? 如果他们确实想要允许特权构建,则只是失败并显示错误并让操作员传递 --privileged 选项。

你想让 shell 交互。 你想要stdout << requested_cap, stdin.gets == 'y' 。 这是验证所需功能的另一种方法

@cpuguy83

有人可能只需要能够做一件非常具体的事情……防止黑客入侵的事情。

这个人想要docker build --cap-add=caps_array caps_array.include? requested_cap 。 这是验证所需功能的另一种方法

所以我问:为什么RUN Dockerfile RUN中的Dockerfile仍然不支持--cap-add--cap-drop等? 没有人对此争论不休。 3年过去了!

@andrew-aladev 我假设没有人反对这种语法,因为已经明确指出 dockerfile 语法会被冻结,直到构建器被重写/重构/与主引擎分离。 https://github.com/docker/docker/issues/29719#issuecomment -269342554

更具体地说,问题的标题和 OP 正在请求 --privileged build

这让 Fonzie 兴奋起来:Fonzie .

能够在build步骤中运行strace有很大帮助。
目前,我通过将所有需要调试的东西移到run步骤来解决这个问题 - 不理想。

有谁知道为什么它会在run而不是build步骤中工作? 即,历史原因。
是否有strace的替代方案,无需太多许可或配置即可工作?

有一个建议的解决方案/解决方法
https://github.com/docker/docker/issues/6800#issuecomment -50494871 :

如果您在 docker build 中遇到问题,您可以使用“构建器容器”:
docker run --cap-add [...] mybuilder | docker build -t myimage -

有人(可能是@tiborvass)可以详细说明这一点吗? 这里的mybuilder是什么类型?
带有一些 ENTRYPOINT 的图像名称? 或者是[...]mybuilder的图片部分指的是
到 shell 脚本? 我如何说服docker run将 context.tar.gz 传递到docker build -
如果这真的是这里发生的事情。 提前致谢,史蒂芬

@sneumann mybuilder将是一个图像名称,并且确实有一些CMDENTRYPOINT 。 该变通方法的工作合同是mybuilder将必须tar容器内的上下文并让它进入标准输出。 这被传递到docker build的标准输入,感谢 shell 管道|并且被认为是上下文,因为docker build -t myimage -的上下文路径是- .

查看代码时有点奇怪,似乎此选项在build命令中可用:

有更多人知道为什么它没有被应用吗?

@mbana --security-opt适用于原生 Windows 容器,支持“credentialspec” https://github.com/docker/docker/pull/23389

是否可以修改它并使其持久化,以便未来的build将启用ptrace

对于任何感兴趣的人,这里有一些很好的链接:

我已经看到很多人声称不需要此功能,因为可以将构建更改为不需要某些特权操作,但没有关于如何处理“docker in docker”案例的建议。 如果构建需要运行docker命令,例如拉下一些我们想要在这个内部发布的图像,或者构建一个子图像,我们应该如何在没有某种特权的情况下做到这一点构建选项?

现在我将使用docker rundocker commit来解决这个问题,但如果docker build可以支持这个用例就太好了。

@scjody听起来像你想要的 #31257

@ cpuguy83我不确定这是否涵盖了在这种情况下发生的情况,但是一旦合并,我会

嗨,我想把我的名字放在请执行这顶帽子上。 或者也许有人可以指出我的问题有不同的解决方案(这里是docker noob)?

我正在尝试基于官方centos/systemd镜像构建一个镜像,并使用 Saltstack 配置它。 这需要使用 systemd 启动(并且可能重新启动)salt-minion 守护进程,如果没有特权模式就无法完成(AFAIK)。

@onlyanegg我认为在那种情况下,Saltstack 在很大程度上取代了构建器的功能; 请记住,每个RUN语句都在一个新容器中执行,此时前一个构建容器将停止,并提交到图像/层。

您是否考虑过通过运行容器并提交结果( docker commit )来执行构建?

感谢您的回复,@thaJeztah。 我没有意识到这就是RUN指令所做的。 我确实阅读了这个问题的大部分内容,所以我知道docker build -> docker run -> docker commit解决方法,这就是我最终可能会做的。 我只是更喜欢用一个文件来描述我的形象——看起来更整洁。 也许我可以将所有这些步骤放在打包机后处理器中,然后我就可以了。

为什么这个被如此忽视? 在容器、kubernetes 和 minikube 时代,以及在 CI 和开发环境统一中使用 docker 时,此功能非常重要。

@onlyanegg您应该能够在 _without_ 特权模式下重新启动服务。 如果您有一个 Dockerfile 来说明这一点(即“此 Dockerfile 第 8 行的RUN命令不起作用,因为它需要特权模式”),我会非常乐意看一看!

@derberg正是! 在容器、CI、CD 时代,重要的是可以包含构建工具(在安全意义上)。 如果您允许特权模式,则必须显着改变使用 CI 工具(如 Jenkins、Travis、Codeship 等)的方式。同样的问题:如果您有一个需要特权模式的 Dockerfile,我很乐意查看以提出替代方案。

谢谢!

@jpetazzo尝试获取其中包含

FROM ubuntu:16.04

# Get dependencies for curl of the docker
RUN apt-get update && apt-get install -y \
    curl \
    sudo \
    bash \
    && rm -rf /var/lib/apt/lists/*

RUN curl -sSL https://get.docker.com/ | sh

现在构建并启动它。 启动后运行service docker start以启动 docker 守护进程。 然后检查服务service docker status

  • 具有特权标志状态没问题,您可以毫无问题地启动容器
  • 没有旗帜,它永远不会开始

@jpetazzo ech,刚刚注意到您是 https://github.com/jpetazzo/dind 的创建者 :) 所以您知道

无论如何,所以您知道运行需要特权标志。 所以现在你可以想象一群人在某个环境中工作,并希望有一个统一的开发环境,里面已经有一些预配置的东西,例如带有预装组件的 minikube 或其他任何东西

那么,有没有办法在docker build挂载 NFS 或 SMB 共享?

@derberg这些步骤不起作用,即使构建容器正在运行--privileged ; docker 包(和安装脚本)是(例如)在 Ubuntu 16.04 上安装内核包。
这正是--privileged对于docker build --privileged是个坏主意的原因,因为它可以对 _host_ 进行更改。

尽管 docker 在 _running_ 时需要特权,但安装本身不需要这个; 例如,这是您在映像中安装 docker 的步骤;

docker build -t foo -<<'EOF'
FROM ubuntu:16.04

RUN apt-get update && apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common \
    && rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
RUN apt-get update && apt-get install -y docker-ce \
    && rm -rf /var/lib/apt/lists/*
EOF

并且你可以很好地运行它(我在这里使用--privileged ,但也许更细粒度的权限是可能的):

docker run -it --rm --privileged -v /var/lib/docker foo dockerd --debug

对于真正需要在特权模式下构建 docker 映像的人,这是我如何规避此问题的方法。 它可能无法解决所有情况,但可以在某些情况下提供帮助。

该方法需要一个 Dockerfile、一个 docker-compse 文件和一个 shell 脚本。

Dockerfile

它与构建映像所需的内容相同。 唯一的区别是,停在您需要进行特权操作的地方,不要包括它们。 它们需要由 docker-compose 作为脚本运行。 例如:

FROM ubuntu:16.04
RUN apt-get update && apt-get install <your packages>
# And more commands
......

## Below are the operations you intended to run in privileged mode when building the image, which does not work.
# More commands....
## But they now are moved to a separated shell script and it will be included in the image
COPY further-commands-to-run-in-privileged-mode.sh /

那些需要在特权模式下运行的命令现在在further-commands-to-run-in-privileged-mode.sh 。 它包含在映像中,稍后将由 docker composer 运行以完成构建过程。

docker 撰写文件

撰写文件是关键。 它将首先从 Dockerfile 上方构建映像,然后以特权模式从该映像启动一个容器,然后您就可以在那里进行特权操作。 例如:

version: '3'

services:
  your_service:
    container_name: your_container
    # First build the image from the Dockerfile
    build:
      # Change this to where you keep above Dockerfile
      context: ../docker-build
    image: "your_image_name:your_image_tag"

    # Then start a container from the just built image in privileged mode to finish what's left
    entrypoint: /further-commands-to-run-in-privileged-mode.sh
    privileged: true

构建图像

以下步骤也可以保存在 shell 脚本中。

# First build the image and container(in privileged mode)
docker-compose -f docker-compose.yml up

# Then commit the temporary build container to a new image, change the ENTRYPOINT to what you want
docker commit \
    -c 'ENTRYPOINT ["/bin/bash"]' \
    <build container name> \
    <final image name>:<final image tag>

# Remove the temporary build container
docker rm <build container name>

@thaJeztah我没有安装问题,我在构建过程中启动 docker 服务并拉取一些图像以使它们在开箱即用的图像中可用时遇到问题。

将以下脚本添加到您的 Dockerfile 中,您将看到 docker 服务永远不会启动

#!/bin/bash

service docker start

sleep 20

service docker status

docker pull busybox

@derberg好的,我明白了! _个人_,如果我想在dind容器中包含图像,我会下载它们(例如使用reg ),并且我会在容器第一次启动时加载它们。 为什么? 因为如果你在构建过程中拉取镜像,镜像才会工作_仅当dind以相同的存储驱动程序启动时_。 换句话说,您的图像可能会或可能不会在其他机器上运行。

此外,如果您的图像很大(即除了busyboxalpine之外的任何其他图像),您最终会得到一个非常大的 DinD 图像......

我很想更多地了解您的最终用例——因为我相信我们可以帮助您找到一种比烘焙巨大的 DinD 图像更有效的方法:-)

(否则, @kraml提出的解决方案相当优雅!)

另见https://github.com/moby/moby/blob/master/contrib/download-frozen-image-v2.sh
仅使用 bash+curl+tar 下载图像。
我们在这里使用它: https :

@jpetazzo我们已经使用了这样的解决方法 build-run-commit,但是是的,从我的角度来看,它仍然是一种解决方法。 用例与 kubernetes 和 minikube 环境非常相关,目前我们无能为力。 现在我们只能使用 docker 作为守护进程在 docker 中启动 minikube,使用 virtualbox 或其他 vm 驱动程序不起作用,所以我们依赖于dind方法

在尝试构建包含遗留应用程序(非常正常的用例)的映像时遇到此问题,安装程序尝试运行 sysctl 命令并失败。

回到这个线程并回顾整个 4 年 (!!!) 关于如何向 docker build 命令添加某种特权功能的问题,似乎这种情况下的可用选项要么是一堆讨厌的 sed 命令来修改安装程序以删除 sysctl 调用,或多阶段构建 -> 运行 -> 提交管道。 我同意@derberg 的观点,即“构建 -> 运行 -> 提交”感觉是一种解决方法(imo 是一种粗暴/hacky 的解决方法),而且我认为我的用例并不是那么独特。 检查其他线程 我看到很多人报告各种应用程序和数据库安装的问题,由于缺乏权限, docker build命令失败。

此时,docker run 命令支持广泛的“特权”选项,以及“使用 --cap-add 和 --cap-drop 对功能进行细粒度控制”。 因此,我认为基于安全或技术的反对意见是没有实际意义的。 如果特权运行选项与“--cap-add”和“--cap-drop”一起添加,具有安全意识的工程师可以选择将特权构建限制为仅包含其构建所需的特定功能。

你好 ,

我之前已经报告过这个,同样的问题。

那些只想在 VM 和容器上使用相同用户 ID 为每个 VM 运行一个容器,使用 docker 作为打包工具的人呢?

是否仍然存在与此相关的安全问题?

遇到了这个问题。 真的可以使用功能进行构建。

也遇到了这个问题。
当使用 docker 作为 CI/CD slaves 时它非常有用,这可能需要docker build特权权限才能在构建从属 docker 映像时安装 CI/CD 构建/测试工具链。
我等这个功能已经等了很多年了,真的希望将来能得到支持。

我真的不明白为什么开发人员对 docker image 的 --privileged 有如此多的反对。
如果用户想用脚射击自己,为什么不让他们呢? 只需放置一条警告消息即可。 已经有实现同样事情的变通方法,为什么不让真正需要它的用户更容易呢?
已经4-5年了,在这方面没有任何进展。
太棒了...

截至今天,甚至还没有实现此功能:
运行 --cap-add=SYS_PTRACE
这将满足许多用户的需求..

你能否建议我如何在 Gentoo Linux 主机上构建这个 Dockerfile:

FROM gentoo/stage3-amd64
# Download and extract latest portage
RUN wget http://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2 && \
    wget http://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2.md5sum && \
    md5sum -c portage-latest.tar.bz2.md5sum 
RUN tar -xjvf portage-latest.tar.bz2 -C /usr
RUN emerge dev-lang/go

因为我在emerge-ing dev-lang/go时收到这个错误:

##### Building Go bootstrap tool.
cmd/dist
 * /var/tmp/portage/sys-apps/sandbox-2.12/work/sandbox-2.12/libsandbox/trace.c:_do_ptrace():75: failure (Operation not permitted):
 * ISE:_do_ptrace: ptrace(PTRACE_TRACEME, ..., 0x0000000000000000, 0x0000000000000000): Operation not permitted
/usr/lib64/libsandbox.so(+0xb692)[0x7fd10e265692]
/usr/lib64/libsandbox.so(+0xb778)[0x7fd10e265778]
/usr/lib64/libsandbox.so(+0x6259)[0x7fd10e260259]
/usr/lib64/libsandbox.so(+0x6478)[0x7fd10e260478]
/usr/lib64/libsandbox.so(+0x7611)[0x7fd10e261611]
/usr/lib64/libsandbox.so(execve+0x3f)[0x7fd10e2634ff]
bash[0x41d8ff]
bash[0x41f387]
bash[0x420138]
bash[0x4219ce]
/proc/330/cmdline: bash ./make.bash 

 * ERROR: dev-lang/go-1.9.2::gentoo failed (compile phase):
 *   build failed
 * 
 * Call stack:
 *     ebuild.sh, line 124:  Called src_compile
 *   environment, line 1034:  Called die
 * The specific snippet of code:
 *       ./make.bash || die "build failed"
 * 
 * If you need support, post the output of `emerge --info '=dev-lang/go-1.9.2::gentoo'`,
 * the complete build log and the output of `emerge -pqv '=dev-lang/go-1.9.2::gentoo'`.
 * The complete build log is located at '/var/tmp/portage/dev-lang/go-1.9.2/temp/build.log'.
 * The ebuild environment file is located at '/var/tmp/portage/dev-lang/go-1.9.2/temp/environment'.
 * Working directory: '/var/tmp/portage/dev-lang/go-1.9.2/work/go/src'
 * S: '/var/tmp/portage/dev-lang/go-1.9.2/work/go'

如何在没有--cap-add=SYS_ADMIN --device /dev/fuse--privileged情况下运行它?

RUN apt-get -y install unionfs-fuse
RUN unionfs-fuse -o cow dir1=RW:dir2=RO dir3/

我可以在入口点使用单独的 bash 文件来完成,但我需要单个 Dockerfile

@amd-nick 您对构建期间RUN unionfs-fuse ...行的期望是什么? 即使这样有效,它也只会在那个RUN期间挂载文件系统,并在下一步中消失。

@thaJeztah很难为我解释。 我正在尝试修改这个 repo 。 我可以跳过建筑物上的这条线吗?

你好

docker build 随机选择一个从零“0”开始的主机名,这会破坏我们的应用程序,我尝试在这种情况下在我的 DockerFile 中运行“主机名”,但遇到了同样的问题。

我还希望可以选择使用 RUNP 运行 docker build,或者在构建期间选择主机名。

有没有人试过用Kaniko构建这些类型的图像? 我刚刚在 Docker for Mac 上使用@maneamarius的 Dockerfile 完成了它,一旦您使用--cap-add=SYS_PTRACE调用 Kaniko 的docker run “build”命令,它似乎就可以成功构建。 虽然,我在本地加载生成的 tarball 时遇到了一些麻烦,RAM 使用率有点高,因为它不能使用 overlayfs,而且层缓存仍然是 WIP。 如果我推送到注册表,事情可能会正常工作,但我还没有尝试过。

docker run --cap-add=SYS_PTRACE --rm -v $(pwd):/workspace gcr.io/kaniko-project/executor:latest --dockerfile=Dockerfile --context=/workspace --tarPath=/workspace/test.tar --destination=test  --single-snapshot

拥有此功能将极大地有助于在 Redhat/CentOS 基础镜像上通过 Puppet 构建 Docker 镜像。

自从我上次发布以来,我一直在跟进 Kaniko的变化。 它们不再在内存中压缩,而是压缩到磁盘上,这意味着支持描述大图像的 Dockerfile。 层缓存仍然是一个 WIP,但他们有一个选项可以暂时缓存基本图像(这意味着目前没有快速的RUN迭代保存和运行类型的工作,但我们可以缓存alpine , ubuntu ,以及任何流行的基础)。

在这种情况下,我已经成功构建了@maneamariusDockerfile,该文件在此项目/演示出现了 Golang,而无需修改@maneamarius的 Dockerfile 或以任何方式将其切碎编辑:我已经必须修改Dockerfile以将 gentoo 基础映像固定到本文发布时的latest版本。否则,它仍然未修改。 ):

https://github.com/nelsonjchen/kaniko-privileged-maneamarius-moby-1916

我还配置了 Azure Pipelines 以将 Dockerfile 构建为带有--cap-add=SYS_PTRACE Kaniko 映像,加载 Kaniko 的输出 tarball,并在生成的映像中运行go version 。 我认为一些交互式的“生命证明”会很有趣。 这里的一些早期评论也关注 CI 系统,所以我想我会配置一个公共 CI 系统也能正常工作。 顺便说一句,Travis CI 被考虑过,但构建输出太长,它被终止了,Azure 对 166k 行的输出非常满意。 如果 Dockerfile 构建的输出行数减少了大约 70k,那么它可能会在 Travis CI 上取得成功。 指向 Azure Pipeline 构建输出的链接位于自述文件的顶部。

使用 buildah 卢克

我正在关闭这个问题,因为该功能现在可用docker buildx build --allow security.insecure

https://github.com/docker/buildx/blob/master/README.md# --allowentitlement
https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md#run ---securityinsecuresandbox

@AkihiroSuda我已将我的buildx 。 当我尝试你提到的命令时,它给了我一个错误

$ docker buildx build --allow security.insecure -t sample-petclinic -f Dockerfile .
[+] Building 0.0s (0/0)                                                                                                                                                         
failed to solve: rpc error: code = Unknown desc = entitlement security.insecure is not allowed

Docker version

Client: Docker Engine - Enterprise
 Version:           19.03.2
 API version:       1.40
 Go version:        go1.12.8
 Git commit:        c92ab06
 Built:             Tue Sep  3 15:57:09 2019
 OS/Arch:           linux/amd64
 Experimental:      true

Server: Docker Engine - Enterprise
 Engine:
  Version:          19.03.2
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.8
  Git commit:       c92ab06
  Built:            Tue Sep  3 15:55:37 2019
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc:
  Version:          1.0.0-rc8
  GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

buildx 文档: For entitlements to be enabled, the buildkitd daemon also needs to allow them with --allow-insecure-entitlement

谢谢@AkihiroSuda 。 它现在起作用了。

只是为了添加另一个用例。
我正在尝试使用测试数据库修复 ibmdb2 容器的 dockerfile 构建
IBM 从集线器中删除了 v10 映像。 但是 v11 数据库映像仅以 --privileged 开头。
因此,在 Dockerfile 中设置数据库的所有代码现在都不起作用,因为 db2 没有特权就无法启动。 :(
使用 docker run 和 docker commit 似乎有一个复杂的解决方法。
在高效的构建管道中,这会产生很多额外的复杂性。

我不得不问这样https://github.com/maneamariushttps://github.com/moby/moby/issues/1916#issuecomment -361173550

为什么支持这件事这么重要? 构建确实在引擎盖下执行运行。

在这个特定的用例中,特权构建选项将支持一种“向后兼容性”,我知道在我的网络研究之后我不是唯一一个遇到这个问题的人。

@uvwild我不确定这是否对您的用例有帮助,但您可以尝试使用kaniko构建您的图像将在没有--privileged--cap-add <capability which is needed>来解决您的问题。

我接受它不是您期望的完整解决方案,而是一种更简单的解决方法,可能适合您的构建管道。

编辑:正如@a​​lexey-vostrikov 所说,对于需要--privileged来构建图像的用例, buildah可能是一个更可行的解决方案

此页面是否有帮助?
0 / 5 - 0 等级