Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker doesn't configure UTS namespace or /etc/hostname correctly #14282

Closed
awh opened this issue Jun 30, 2015 · 19 comments
Closed

Docker doesn't configure UTS namespace or /etc/hostname correctly #14282

awh opened this issue Jun 30, 2015 · 19 comments

Comments

@awh
Copy link

awh commented Jun 30, 2015

Edit: My assertion about setting domainname may be suspect; see phemmer's comment and discussion below. The issue of erroneously passing the FQDN to syscall.Sethostname remains however.

Environment

vagrant@vagrant-ubuntu-utopic-64:~$ docker --version
Docker version 1.7.0, build 0baf609

Problem

Docker accepts a fully qualified domain name as the argument to --hostname, and models separate Hostname and Domainname fields in runconfig.Config; however once inside libcontainer only Hostname is modelled, and this erroneously includes the domain name which is then fed into syscall.Sethostname with the following results:

vagrant@vagrant-ubuntu-utopic-64:~$ docker run --hostname test.example.com -ti ubuntu
root@test:/# hostname
test.example.com
root@test:/# domainname
(none)

This is not correct; the value passed to syscall.Sethostname should be the unqualified hostname, and the remainder to syscall.Setdomainname. This would yield the expected output:

vagrant@vagrant-ubuntu-utopic-64:~$ docker run --hostname test.example.com -ti ubuntu
root@test:/# hostname
test
root@test:/# domainname
example.com

Currently, libcontainer does not invoke syscall.Setdomainname at all, leaving the domain name parameter of the UTS namespace uninitialised.

Docker is also incorrectly generating an /etc/hostname file with the fully qualified name - again this should be the unqualified name, and the FQDN set by aliasing in /etc/hosts.

It could also be argued that --hostname should be renamed to --fqdn, or changed so that it admits only an unqualified name and companioned by a new --domainname option to set the remainder.

Finally, the error message is uninformative:

docker run --hostname 012345678901234567890123456789012345678901234567890123456789.example.com -ti ubuntu
Error response from daemon: Cannot start container c1bb14c2a10b2341c185aed804ab6f625ca7a1164ea90ea4fd37ea56b6e2bed0: [8] System error: invalid argument

Consequences

@awh awh changed the title Docker does configure UTS namespace or /etc/hostname correctly Docker doesn't configure UTS namespace or /etc/hostname correctly Jun 30, 2015
@phemmer
Copy link
Contributor

phemmer commented Jun 30, 2015

The current behavior is the correct behavior. The value you pass to docker in --hostname is supposed to be the value you get back from the commands hostname and uname -n.
The "domainname" that you are referring to (the domainname command) is not related. From man 1 domainname:

domainname - show or set the system's NIS/YP domain name

What I think you are looking for is the dnsdomainname:

# docker run --hostname test.foo.com -ti ubuntu dnsdomainname
foo.com

@awh
Copy link
Author

awh commented Jun 30, 2015

What I think you are looking for is the dnsdomainname:

I am aware of dnsdomainname. My main concern is that we should not be setting the entire FQDN as the hostname, in either /etc/hostname or with syscall.Sethostname. Hostname should not include a DNS domain - naming of hosts is orthogonal to IP addressing and DNS.

This is strongly implied by man hostname:

The  recommended method of setting the FQDN is to make the hostname be an alias for the fully qualified name using /etc/hosts, DNS,
       or NIS. For example, if the hostname was "ursula", one might have a line in /etc/hosts which reads

              127.0.1.1    ursula.example.com ursula

This would yield the following:

$ hostname
ursula
$ dnsdomainname
example.com
$ hostname -f
ursula.example.com

I believe this would give you the correct behaviour in terms of field length limits: unqualified hostname limited to 64 characters by the kernel, and the domain part limited by the resolver implementation. (Incidentally, this interpretation lends strength to your argument about domainname - that field is also kernel limited to 64 characters, in contravention of RFC1035 2.3.4 which specifies a maximum length of 255 characters on fully qualified names, so I think you're right that it's not intended to hold a DNS domain). Thoughts?

@phemmer
Copy link
Contributor

phemmer commented Jun 30, 2015

I'm really confused then. If you don't want a fully qualified hostname, then don't pass a fully qualified hostname.

@awh
Copy link
Author

awh commented Jun 30, 2015

I'm really confused then. If you don't want a fully qualified hostname, then don't pass a fully qualified hostname.

I do want a fully qualified hostname. My argument is that the way a Linux system is properly configured with such is to put the unqualified part into /etc/hostname and sethostname, and the domain part in /etc/hosts as per the recommendations in man hostname.

@awh
Copy link
Author

awh commented Jun 30, 2015

For further clarification; the original use of /etc/hostname and the value of sethostname was to store an unqualified name - as I said, DNS was orthogonal. Over time a common misconfiguration crept in of putting the FQDN into /etc/hostname (mainly I suspect because folks didn't realise that the correct way was to put an alias in /etc/hosts). To cope with this common misconfiguration, most tools have been bodged to cope with either scenario - see man hostname:

       /etc/hostname  Historically  this file was supposed to only contain the hostname and not the full canonical FQDN. Nowadays most
       software is able to cope with a full FQDN here. This file is read at boot time by the system initialization scripts to set  the
       hostname.

So for most things it's a non issue - everything you're likely to deploy inside the container can cope with things being configured either way. What is not the same though is the artificial limit on FQDN imposed by storing the entire qualified name in a kernel field which is applying a limit intended for the unqualified hostname.

@phemmer
Copy link
Contributor

phemmer commented Jun 30, 2015

I see what you're wanting now. But I argue the behavior of the docker --hostname parameter should not be touched. The parameter sets the system hostname, which is a special value tracked by the kernel. The domain name is irrelevant to the kernel. It doesn't care at all.
Now if the request is to automatically append a domain name to the hostname, and use it in the /etc/hosts file, this should be a new feature.

Also, using a fully qualified host name is not an uncommon practice. There are 2 different schools of thought about the hostname. The redhat school of thought, and the debian school of thought.
The redhat school says that hostname should be fully qualified. The debian school says that hostname should not be fully qualified.

By changing the behavior of --hostname, you may end up breaking redhat based containers, which many tools expect a fully qualified hostname (yes, the issues can usually be worked around though).

I also personally find it rather annoying when a tool I'm using assumes it knows better than me, tries to be smart, and doesn't do what I told it to do. If I want to shoot myself in the foot, that's my problem.

@estesp
Copy link
Contributor

estesp commented Jun 30, 2015

To add to @phemmer's comments, the way it works today is because we fixed an issue just under a year ago to support both Fedora/Redhat "view of the world" for hostnames as well as Ubuntu. I'm curious if something has changed in the overall code path because when I fixed that issue, hostname on Ubuntu Docker images still resulted in the prefix, not FQDN, if I remember correctly. I can look back at the issue and PR and see if we've regressed in some way, but overall, we do have to support both views which makes this whole area tricky.

@awh
Copy link
Author

awh commented Jun 30, 2015

Ahhh, the joys of fragmentation 😄 I appreciate that you have a difficult balancing act to do here - I wasn't aware that Redhat has standardised on storing the FQDN in /etc/hostname and sethostname. What are your thoughts about the artificial limit this imposes on the fully qualified name? It makes a mockery of e.g. #9333, because in reality the entire fully qualified name including domain is restricted to 64 characters... if nothing else is done, the code relating to validating --hostname needs to be revamped.

@cpuguy83
Copy link
Member

cpuguy83 commented Jul 7, 2015

Seems like there is no issue here...Can we close this?

@awh
Copy link
Author

awh commented Jul 8, 2015

I would suggest if you do nothing else you should change the field validation so that you get a sensible error message when you pass an FQDN > getconf HOST_NAME_MAX to -h.

@garyp
Copy link

garyp commented Oct 2, 2015

@estesp There definitely seems to be a regression on Ubuntu:

# docker --version
Docker version 1.8.2, build 0a8c2e3
# docker run --rm -it -h foo.bar.org ubuntu:vivid /bin/bash
root@foo:/# hostname
foo.bar.org
root@foo:/# hostname -f
foo.bar.org
root@foo:/# more /etc/hostname
foo.bar.org
root@foo:/# dnsdomainname
bar.org

I see similar behavior with Debian images.

@phemmer
Copy link
Contributor

phemmer commented Oct 2, 2015

@garyp What's the issue? that's what I would expect to see.

@garyp
Copy link

garyp commented Oct 2, 2015

@phemmer hostname should return the unqualified hostname on Debian/Ubuntu systems (e.g. "foo" in my example above) and, likewise, /etc/hostname should contain the unqualified name. You yourself linked above to the Debian policy on this, which says:

The init script in runlevel S which is symlinked to "/etc/init.d/hostname.sh" sets the system hostname at boot time (using the hostname command) to the name stored in "/etc/hostname". This file should contain only the system hostname, not a fully qualified domain name.

@phemmer
Copy link
Contributor

phemmer commented Oct 2, 2015

hostname is a standard linux utility. It's the same utility on all distros, and behaves the exact same. The difference is that on debian based systems, it's standard for the hostname to not be fully qualified. Meaning that hostname simply shows the value that is set. If you don't want a fully qualified hostname, don't set it fully qualified.

@garyp
Copy link

garyp commented Oct 2, 2015

Agreed on the hostname command. The root problem is that on Debian-based systems Docker dumps the FQDN into /etc/hostname. I can't just pass the unqualified hostname to Docker because then hostname -f will not return the FQDN. In short, on a properly-configured Debian-based system, the following should be true:

root@foo:/# hostname
foo
root@foo:/# hostname -f
foo.bar.org

The standard way to get the above results on Debian-based systems is for /etc/hostname to contain "foo" and /etc/hosts to contain " foo.bar.org foo". There is no way to achieve this state with Docker's current behavior:

  • If I pass --hostname foo to Docker, then /etc/hostname is correct ("foo") but /etc/hosts is wrong (" foo"), causing hostname -f to not return the FQDN.
  • If I pass --hostname foo.bar.org to Docker, then /etc/hosts is correct (" foo.bar.org foo") but /etc/hostname is wrong ("foo.bar.org"), causing hostname to return the FQDN instead of the unqualified name.

@phemmer
Copy link
Contributor

phemmer commented Oct 2, 2015

Yes, that i'll agree with. That is what I was referring to with the comment:

Now if the request is to automatically append a domain name to the hostname, and use it in the /etc/hosts file, this should be a new feature.

I'm not opposed to something which would allow the desired behavior, just that it should be a new feature. The --hostname option should remain setting the hostname to the kernel exactly as you passed it. Docker doesn't know what distro you're running, and even if it did, that kind of automatic switch would be a bad idea in my opinion.

The best solution I can think of for this would be a --fqdn option. If provided, it would be used in /etc/hosts. Then hostname would be the value provided to --hostname, and hostname -f would be the --fqdn value. This would be true for all distros.

But I think it would be best to track such a feature request in a new issue, so it has a clean history, and is clear that it is a feature request, and not a bug report.

Edit:
Another idea, use the --add-host option. If no colon (:) is provided in the value, the value is added to the host's line in /etc/hosts.

@thockin
Copy link
Contributor

thockin commented Feb 10, 2016

To add to this debate, from #20180.

Linux has a limit of 64 characters for the in-kernel hostname (syscall.Sethostname), but the limit for DNS domains is 253 characters (a set of tokens <= 63 characters each). Smooshing the domainname into the hostname means my whole host+domain has to be less than 64. As far as I can tell there is no real workaround for this - it is just not possible to use longer domainnames.

Standard tools like hostname and dnsdomainname already operate correctly on docker, which populates the /etc/hosts file properly for the hostname. There's not actually any reason to smoosh them together, except to act more like (broken) RedHat systems with the FQDN in /etc/hostname.

The root of the problem is that the API has 2 fields (hostname and domainname) but the CLI only has hostname, but docker wants to offer both the shortest one-token name AND the FQDN as /etc/hosts aliases. I'm sort of asserting that this is semantically wrong, though the horse has already left the barn.

CLI --hostname=foo.bar.com becomes:

  • hostname foo.bar.com
  • hostname -f foo.bar.com
  • dnsdomainname bar.com
  • /etc/hostname foo.bar.com
  • /etc/hosts foo.bar.com foo # foo is what is broken

API hostname=foo domainname=""

  • hostname foo
  • hostname -f foo
  • dnsdomainname ``
  • /etc/hostname foo
  • /etc/hosts foo

API hostname=foo domainname=bar.com

  • hostname foo.bar.com # this is what is broken
  • hostname -f foo.bar.com
  • dnsdomainname bar.com
  • /etc/hostname foo.bar.com # broken
  • /etc/hosts foo.bar.com foo

I'm assuming that any solution here has to retain the CLI's set of behaviors - as broken as it is semantically, it is useful and likely to cause pain. I am also assuming that we do not want to add new CLI flags (CLI will just be "wrong" but compatible, for now). Conversely, I am assuming that we can fix the two-part API case without causing too much anguish. Do I interpret correctly?

@thockin
Copy link
Contributor

thockin commented Feb 10, 2016

The PR attached here adds a new flag to the API which says whether to make hostname be the FQDN or not.

A simpler approach might be to make the CLI not split the --hostname flag at all, leaving the domainname API field empty. The /etc/hosts builder can do the split and offer both foo and foo.bar.com as hosts aliases. No new API fields required.

@thockin
Copy link
Contributor

thockin commented Feb 10, 2016

#20200 implements the 2nd approach, which I think is a much better option. I'm happy to polish it off if someone ACKs the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants