Changing Docker hostnames—with namespaces!

Oct 13, 2016 · by Dave Vasilevsky

At Evolving Web we love using Docker! So when I needed to do work on several different sites, I just spun up a few Docker containers, and now I've got this:

Bad docker hostnames

Three shells in three different containers, and it's super hard to tell which is which.The hostnames are just random hex strings—so confusing!

If I had thought ahead, I could have set the hostnames with the --hostname option to docker run. But I forgot, and now I can't change it:

[email protected]:/drupal/docroot$ sudo hostname "prototypes"
hostname: you must be root to change the host name

That's weird: I'm using sudo, but it still says I must be root! It looks like Docker limits the kernel capabilities of its containers, so I can't change hostnames from within a container. Am I just stuck with these random hostnames? I better learn more about how this whole container thing works.

Containers are just namespaces

So how does each container have a separate hostname, anyway? I know that containers are just processes in Linux namespaces—so there must be a namespace for hostnames. I can use the lsns command to explore all my namespaces:

vasi$ sudo lsns
        NS TYPE  NPROCS   PID USER COMMAND
4026531836 pid       84     1 root init      
4026531837 user     142     1 root init      
4026531857 mnt        1    14 root kdevtmpfs
4026531957 net       84     1 root init      
4026532300 mnt       17  1778 root /usr/bin/python /usr/local/bin/supervisord -c
4026532301 uts       17  1778 root /usr/bin/python /usr/local/bin/supervisord -c
4026532302 ipc       17  1778 root /usr/bin/python /usr/local/bin/supervisord -c
4026532303 pid       17  1778 root /usr/bin/python /usr/local/bin/supervisord -c
...

There are so many different types of namespaces: pid, user, ipc, uts, mntnet. I have no idea which one involves hostnames, so I checked Wikipedia: It's uts that manages that! Each uts namespace has one hostname, which is shared among all the processes in that namespace.

That gives me an idea: I can't change the hostname from a container because of limited capabilities. But I could totally launch a new process in the same namespace, and this new process would have no capability limits—so it could change the hostname. And that change would be shared with the container! Let's try it!

I'll use the nsenter command to get inside the right namespace for container 378dd3233752. We have to give nsenter a process ID, not a container ID—but no worries, Docker can translate for me:

vasi$ docker inspect -f '{{ .State.Pid }}' 378dd3233752
2868

Now I have all I need to run nsenter. It gives me a shell in the right namespace, where I can just set the hostname:

vasi$ sudo nsenter --target 2868 --uts
378dd3233752$ hostname "prototypes"

Success!

When I login to the container again, I see the hostname prototypes instead of a bunch of hex characters! Now it's easy to tell which shell is which:

Good hostnames

I'm sure tons of other things become so much easier when you understand namespaces. What cool tricks have you found?

 

Discuss at Hacker News | Reddit