在docker容器中运行的Python程序依赖于'uname -r'

我有一个Python程序,只能在Linux的某些发行版(如CentOS,Ubuntu等)中运行。 我想让它在CentOS7容器中运行,但是由于以下代码返回'4.9.49-moby':

import platform platform.release() 

该程序期望find一个Linux内核版本,即“3.10.0-327.el7.x86_64”。

假设我无法修改程序的源代码。

什么是我可以做的事情将解决这个问题?

我试着围绕'uname -r'编写一个包装脚本来返回我想要的。 但是这并没有什么帮助,因为Python显然是直接从内核中获取它的。

Python只是简单地调用uname系统调用来获取这个信息,这个信息总是会返回关于当前正在运行的内核的信息。 在不修改源代码的情况下覆盖返回值将会非常棘手。

可以使用函数插入完成此操作,例如这里所述。 这需要修改映像以包含包装器库和必要的环境设置,或者需要在Docker运行命令行上传递许多附加参数。

这是一个简单的例子。 我从一个香草形象开始,并在Python中调用os.uname()

 $ docker run -it --rm fedora python3 Python 3.6.2 (default, Sep 1 2017, 12:03:48) [GCC 7.1.1 20170802 (Red Hat 7.1.1-7)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.uname() posix.uname_result(sysname='Linux', nodename='fd2d40cb028b', release='4.13.15-100.fc25.x86_64', version='#1 SMP Tue Nov 21 22:45:32 UTC 2017', machine='x86_64') >>> 

我想release字段显示1.0.0 。 我首先为uname系统调用创build一个包装器:

 #define _GNU_SOURCE #include <dlfcn.h> #include <stdio.h> #include <string.h> #include <sys/utsname.h> /* Function pointers to hold the value of the glibc functions */ static int (*real_uname)(struct utsname *name) = NULL; /* wrapping write function call */ int uname(struct utsname *name) { int res; real_uname = dlsym(RTLD_NEXT, "uname"); res = real_uname(name); if (res == 0) { memset(name->release, 0, _UTSNAME_RELEASE_LENGTH); strncpy(name->release, "1.0.0", 5); } return res; } 

我编译共享库:

 $ gcc -fPIC -shared -o wrap_uname.so wrap_uname.c -ldl 

现在我可以将其注入泊坞窗图像并预加载共享库。 添加的关键是-v注入库和-e LD_PRELOAD以使连接器预加载它:

 $ docker run -it --rm \ -v $PWD/wrap_uname.so:/lib/wrap_uname.so \ -e LD_PRELOAD=/lib/wrap_uname.so fedora python3 

正如你所看到的,这给了我们期望的结果:

 Python 3.6.2 (default, Sep 1 2017, 12:03:48) [GCC 7.1.1 20170802 (Red Hat 7.1.1-7)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.uname() posix.uname_result(sysname='Linux', nodename='dd88d697fb65', release='1.0.0', version='#1 SMP Tue Nov 21 22:45:32 UTC 2017', machine='x86_64') >>> 

您可以使用docker:dind在CentOS容器中运行Ubuntu容器(或任何其他兼容的发行版)。