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:

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:

docker@378dd3233752:/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 , mnt , net . 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:

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

Discuss on Reddit