Dockerfile HOSTNAME Instructions for docker build, like docker run -h

I am trying to set the hostname inside the docker container during build, as some software installations use a randomly generated hostname that is detected and constantly bake this hostname in the configuration.

While you can set the host name when interactively running via run -h, the same functionality is not available using the assembly through the Docker file.

The only way around this is to use the LD_PRELOAD hacks so that I can set the hostname to localhost. LD_PRELOAD hackers have unwanted side effects that are hard for me to work with. Software installation works without problems when using "docker run -it -h localhost".

strace reports that the installer makes a uname call, specifying the host name.

uname({sys="Linux", node="12b0c7c7eacb", ...}) = 0 

Does anyone know how to get around this limitation?

Update 1

This is not a duplicate of the question How to handle a specific host name, for example, -h in the Dockerfile, since it is specifically about the problems "/ etc / hosts" that arise from this file is dynamically generated. This is easy to work as it is a writeable file.

This is about software installations that try to resolve the host name from system calls such as uname and gethostname. From what I can say, this cannot be circumvented, since the host name cannot be changed in the container of the running docker. The uname system call calls probable links / proc / sys / kernel / hostname, this is read only and cannot be changed. Usually the hostname command can be run, but this command generates an error that should be root, even if you are the root user. The workaround for this is to use the -h flag, this is not available in assemblies.

Update 2

For those who are looking for a workaround here, this only needs to be used during the docker build, use the -h flag if you need to configure the hostname when starting docker. It is based on someone else's work.

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 Source:

 #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 according to the_the_void , as there is no solution to this problem.

+5
source share
3 answers

Let me see if I understand your question, would you like to create an image that, when launched, has the runtime host name as a container, even if the host name used to build does not match. Right? If so, my question for you is this: can you reconfigure the software to the new host name after installing it?

If possible, I would recommend writing a script that can change the host name and use this script as ENTRYPOINT . Thus, you can guarantee that you corrected the host name at any time when your container is started (with any command), and you do not waste time forcing to maintain a specific host name during assembly, which, according to your own admission hard to do.

+1
source

You can use docker-compose to create your image and assign a host name, for example

 version: '3' services: all: image: testimage container_name: myname hostname: myhost build: context: . 

docker-compose --build up like: docker-compose --build up .

+1
source

I recently had a similar problem.

The solution that worked for me was to set the hostname in the container namespace. To do this automatically, I compiled the following docker build script:

 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) 

Right at the end, new-hostname can be replaced with the desired hostname.

My Dockerfile looks like this:

 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...' 

The first line, which displays change-hostname $(hostname) (where hostname should display the current container identifier), tells the builds script to change the host name for this container. The build script then requests a pid for the container and executes hostname 'new-hostname' in its uts namespace. sleep 1 just gives the build script some time to properly configure the host name. Then I change /etc/hostname and /etc/hosts to include the newly set host name.

It even changes the output of uname -n so I'm sure it will work as a solution to the original question.

0
source

Source: https://habr.com/ru/post/1215715/


All Articles