在 docker 的不同内核中编译代码会受到啥影响?

Posted

技术标签:

【中文标题】在 docker 的不同内核中编译代码会受到啥影响?【英文标题】:what will be impacted for compiling code in different kernel in docker?在 docker 的不同内核中编译代码会受到什么影响? 【发布时间】:2014-07-19 15:41:04 【问题描述】:

对于 c/c++ 源代码,我可以信任 Ubuntu 14.04 主机中用于 redhat6.4 的 docker 容器中的构建吗?还是我需要考虑的任何限制?

我们正在尝试使用 docker 服务于不同的操作系统平台来编译源代码,因为 docker 中的技术是共享主机操作系统的内核,请参阅相关问题What is the relationship between the docker host OS and the container base image OS?

我的主机操作系统是ubuntu 14.04(易于安装docker),内核是3.13.0-24-generic 我的应用平台是redhat 6.4(内核是2.6.32-358.el6.x86_64

当我为 Ubuntu 的 RHEL 创建容器时,内核也更新为 3.13.0-24-generic

我的应用程序是基于 c/c++ 和 java 的。

我认为java对于编译的.jar文件不会有任何问题,因为它是基于jvm的。

而对于 c/c++ 代码,我理解它主要依赖于libc 类型的共享库,而不依赖于内核,因此是否可以将此编译后的代码用于真正的 redhat 环境。

此设置仅用于开发,不用于生产,生成的二进制文件应该安装在带有 RHEL 或 VM 的真正独立机器上。

那么我需要考虑什么?

可能是更多与 lxc 相关的问题。

更新以添加一些示例

我下载了gameoflife代码https://github.com/rvsjoen/game-of-life,在两个系统都编译,找这个案例,因为md5是一样的,结果一样,可信。

这是虚拟机中的redhat 6.4系统

[root@redhat game-of-life-master]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.4 (Santiago)
[root@redhat game-of-life-master]# uname -a
Linux redhat 2.6.32-358.el6.x86_64 #1 SMP Tue Jan 29 11:47:41 EST 2013 x86_64 x86_64x86_64 GNU/Linux
[root@redhat]# ldd gol
    linux-vdso.so.1 =>  (0x00007fffaeaa8000)
    libncurses.so.5 => /lib64/libncurses.so.5 (0x00000033fa000000)
    libc.so.6 => /lib64/libc.so.6 (0x00000033f9c00000)
    libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00000033fb800000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00000033f9800000)
    /lib64/ld-linux-x86-64.so.2 (0x00000033f9400000)
[root@redhat]# md5sum gol
4f3245d3d61b1c73e48537dd612d37c3  gol

这是 docker 容器中的 redhat

bash-4.1# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.4 (Santiago)
bash-4.1# uname -a
Linux f51c7b4e80aa 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
bash-4.1# ldd gol
    linux-vdso.so.1 =>  (0x00007fff5e3c2000)
    libncurses.so.5 => /lib64/libncurses.so.5 (0x00007f2e84863000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f2e844d0000)
    libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f2e842ae000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f2e840aa000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f2e84a8e000)
bash-4.1# md5sum gol
4f3245d3d61b1c73e48537dd612d37c3  gol

c/c++代码有什么例外吗?

【问题讨论】:

【参考方案1】:

在正常情况下,本地编译的代码(C、C++...)也不例外。

正如您所写,程序与libc 交互,而不是内核,除非是非常特殊的情况。

这个libclibrary 不在您的 Ubuntu 主机和 Redhat 容器之间共享。您的容器有自己的libc,它将系统调用抽象到内核。

关于内核本身,请注意,即使 Linux 内核内部趋向于移动,总是在不断发展代码片段,公开暴露的内容(ABI、用户空间应用程序和libc)仍然保持稳定和兼容发布。在极少数情况下,这种兼容性被破坏了,大多数时候,不是故意的。 (见this article)。

所以,是的,使用 RHEL 开发人员是绝对安全的。 Ubuntu 主机上的环境,并信任从该容器生成的构建。

【讨论】:

我真的很感谢这个答案 - 我想在 debian“拉伸”主机(内核 4.9)中运行 ubuntu 映像,askubuntu.com/questions/517136/… 显示 Ubuntu 内核版本为 16.04 的 4.4 或 18.04 的 4.15。现在敢潜入这个“版本地狱”,看看……【参考方案2】:

App不直接使用某个linux内核的最后一个特性没有问题。

Docker 在最低级别工作,只拦截所有“系统调用”。

在 Linux 64 (x64) 中,系统调用是使用 intel / amd 处理器汇编指令进行的:SYSCALL

这个 SYSCALL 是被 LINUX 的 KERNEL “拦截”,并通过内部更改调用的操作与 docker “虚拟化”的。

例如,系统调用“open”,打开一个磁盘文件,将文件的路径更改为另一个正在运行的docker镜像的“root”所在的路径。

我不知道究竟是在内核的哪个级别进行了更改,是在进入“open”时,还是在内部。

因此,在没有 docker 的 linux 中运行的相同二进制可执行文件,在 docker 映像中运行,而无需随时修改可执行文件。

所有“虚拟化”都在 KERNEL 内完成,例如使用 SYSCALL 输入。

但要小心使用内核最新“功能”的应用程序。因为它可能无法正常运行,如果它下面的内核没有那个“功能”。

注意内核级别的安全补丁,下面的内核可能没有这样的补丁。反过来,安装这些安全补丁和维护安全系统更容易,因为它们不是 APP 的“一部分”。这是相对于 VM 映像的另一个优势。

【讨论】:

以上是关于在 docker 的不同内核中编译代码会受到啥影响?的主要内容,如果未能解决你的问题,请参考以下文章

在 Docker 中使用多个基础镜像有啥影响?

Docker和LXC有啥不同

已编译模块的数量是不是会影响 RAM 中 Linux 内核的大小?

docker 宿主机 是啥意思,不安装宿主机好像也可以运行容器

当不同的 CPU 内核在没有同步的情况下写入同一个 RAM 地址时会发生啥?

linux 内核源码包 .config 啥用处