docker构建类docker run-h的docker文件主机名指令
我试图在构建期间在docker容器中设置主机名,因为某些软件安装使用发现的随机生成的主机名,并将该主机名永久地烘焙到配置中 虽然可以在通过run-h交互运行时设置主机名,但通过Dockerfile使用build无法使用相同的功能 解决这个问题的唯一方法是使用LD_PRELOAD hacks,这样我就可以将主机名设置为localhost。LD_预加载黑客有一些不必要的副作用,我在处理这些副作用时遇到了麻烦。使用“docker run-it-h localhost”时,软件安装不会出现问题 strace报告安装程序调用uname来确定主机名docker构建类docker run-h的docker文件主机名指令,docker,dockerfile,Docker,Dockerfile,我试图在构建期间在docker容器中设置主机名,因为某些软件安装使用发现的随机生成的主机名,并将该主机名永久地烘焙到配置中 虽然可以在通过run-h交互运行时设置主机名,但通过Dockerfile使用build无法使用相同的功能 解决这个问题的唯一方法是使用LD_PRELOAD hacks,这样我就可以将主机名设置为localhost。LD_预加载黑客有一些不必要的副作用,我在处理这些副作用时遇到了麻烦。使用“docker run-it-h localhost”时,软件安装不会出现问题 stra
uname({sys="Linux", node="12b0c7c7eacb", ...}) = 0
有人知道如何绕过这个限制吗
更新1
这不是问题的重复,因为它专门讨论动态生成的文件所产生的“/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);
}
定义GNU源
#包括
#包括
#包括
#包括
#包括
#包括
静态int(*real_gethostname)(字符*名称、大小长度);
int uname(结构utsname*buf)
{
int ret;
ret=syscall(SYS_uname,buf);
strcpy(buf->nodename,“localhost”);
返回ret;
}
int gethostname(字符*名称,大小\u t len)
{
常量字符*val;
/*覆盖主机名*/
val=“localhost”;
如果(val!=NULL)
{
strncpy(名称、val、len);
返回0;
}
/*调用实gethostname()*/
返回真实的主机名(名称,len);
}
根据进入\u void,因为这个问题没有解决方案。让我看看我是否理解您的问题,您希望构建一个映像,当作为容器运行时,它具有运行时主机名,即使用于构建的主机名不同。对的如果是这样,我的问题是:在安装软件后,您是否能够重新配置软件,使其具有新的主机名 如果这是可能的,我建议编写一个能够修改主机名的脚本,并将此脚本用作
入口点
。通过这种方式,您可以保证在容器运行时(使用任何命令)已更正主机名,并且不会在构建时花费时间强制支持特定主机名,这一点您自己也承认很难做到。您可以使用来构建映像并分配主机名,例如
version: '3'
services:
all:
image: testimage
container_name: myname
hostname: myhost
build:
context: .
运行方式:
docker compose--build-up
我最近遇到了类似的问题
对我有效的解决方案是在容器名称空间中设置主机名。
为了自动执行此操作,我将以下docker构建脚本放在一起:
docker build . | tee >((grep --line-buffered -Po '(?<=^change-hostname ).*' || true) | while IFS= read -r id; do nsenter --target "$(docker inspect -f '{{ .State.Pid }}' "$id")" --uts hostname 'new-hostname'; done)
打印出change hostname$(hostname)
(其中hostname应打印出当前容器id)的第一行向构建脚本发送信号,以更改该容器的主机名。然后,构建脚本查询容器的pid,并在其uts命名空间中执行hostname'newhostname'
。sleep 1
只给构建脚本一些时间来正确调整主机名。然后修改/etc/hostname
和/etc/hosts
以包含新设置的主机名
这甚至改变了uname-n的输出,因此我很确定它可以作为原始问题的解决方案。我的回答对您有帮助吗?谢谢你的回复,纳撒尼尔;我想你的答案是我在网上唯一能找到的关于这个话题的答案。我正在安装的软件查看/etc/hosts,但使用uname系统调用派生主机名。我将在将来记住您的解决方案。这可能是一个伟大的建议,入口点脚本是我们为所有docker图像所做的。不幸的是,该软件在大约60个位置配置主机名,包括文本文件、xml文件和内部二进制文件。建议的主机名更改方法意味着重新安装软件以及一些附加步骤。这意味着入口点启动时间将从2分钟增加到大约40分钟,这是不可行的。好吧,也许是时候尝试问题跟踪器()了,因为我认为这个功能不存在,或者至少没有遇到过它55分钟前进入\u void谢谢您提供的信息,我认为这是正确的答案。docker compose是在构建步骤中使用指定的主机名,还是仅在运行步骤中使用指定的主机名?我希望看到一个简单构建文件的演示,它在构建时和运行时输出主机名。这只在运行时设置主机名。不是在构建期间。至少在Mac上使用“docker compose version 1.23.2,build 1110ad01”。
RUN echo "change-hostname $(hostname)"; \
sleep 1; \
printf '%s\n' "$(hostname)" > /etc/hostname; \
printf '%s\t%s\t%s\n' "$(perl -C -0pe 's/([\s\S]*)\t.*$/$1/m' /etc/hosts)" "$(hostname)" > /etc/hosts; \
echo 'Installing more stuff...'