【发布时间】:2015-05-23 07:12:54
【问题描述】:
我试图在构建过程中在 docker 容器中设置主机名,因为某些软件安装使用发现的随机生成的主机名并将该主机名永久地烘焙到配置中。
虽然可以通过 run -h 交互式运行时设置主机名,但通过 Dockerfile 构建时无法使用相同的功能。
解决此问题的唯一方法是使用 LD_PRELOAD hack,以便我可以将主机名设置为 localhost。 LD_PRELOAD hack 有一些不想要的副作用,我无法解决这些副作用。使用“docker run -it -h localhost”时,软件安装没有问题。
strace 报告安装程序调用 uname 确定主机名。
uname({sys="Linux", node="12b0c7c7eacb", ...}) = 0
有谁知道如何解决这个限制?
更新 1
这不是问题How to handle specific hostname like -h option in Dockerfile 的重复,因为它专门讨论了动态生成的文件引起的“/etc/hosts”问题。这很容易解决,因为它是一个可写文件。
这是关于尝试从系统调用(例如 uname 和 gethostname)解析主机名的软件安装。据我所知,这是无法解决的,因为无法在正在运行的 docker 容器中更改主机名。 uname 系统调用可能引用 /proc/sys/kernel/hostname,这是只读的,不能更改。通常可以运行 hostname 命令,但是该命令会生成一个错误,即即使您是 root,您也必须是 root。解决方法是使用 -h 标志,这在构建中不可用。
更新 2
对于任何在这里寻找解决方法的人来说,这只需要在 docker 构建期间使用,如果您需要使用 docker run 自定义主机名,请使用 -h 标志。这是基于其他人的工作。
Dockerfile:
RUN gcc -o fakehostname.o -c -fPIC -Wall fakehostname.c
RUN gcc -o libfakehostname.so -shared -W1,export-dynamic fakehostname.o -ldl
RUN ..
export LD_PRELOAD=/u01/app/oracle/libfakehostname.so;\
installer section
..
C 来源:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <stdio.h>
#include <string.h>
static int (*real_gethostname)(char *name, size_t len);
int uname(struct utsname *buf)
{
int ret;
ret = syscall(SYS_uname, buf);
strcpy(buf->nodename, "localhost");
return ret;
}
int gethostname(char *name, size_t len)
{
const char *val;
/* Override hostname */
val = "localhost";
if (val != NULL)
{
strncpy(name, val, len);
return 0;
}
/* Call real gethostname() */
return real_gethostname(name, len);
}
http://github.com/docker/docker/issues 根据 into_the_void,因为没有解决此问题的方法。
【问题讨论】:
-
我的回答对你有帮助吗? stackoverflow.com/a/28922278/1220269
-
感谢您的回复纳撒尼尔;我认为你的答案是我在互联网上能找到的关于这个话题的唯一内容。我正在安装的软件查看 /etc/hosts 但使用 uname 系统调用来派生主机名。以后我会牢记您的解决方案。
标签: docker dockerfile