How to access docker hostname from a service task

Hi,

I want to create a Docker Swarm Service in a Centos environment with 4 replicas- which are created on multiple docker hosts.
In the service tasks created, I want to use the hostname of the respective docker host on which the task is created.
Can someone please let me know how to access the respective docker hostname from inside the service task/container.

you will have to pass that info into the container at startup somehow… use -e (environment) or pass it a a parm (after the image name)

there is no way to discover the host info from inside the container

By using docker templates, I could get the Node.Id in the swarm {{.Node.ID}}. From the node.id, I can get the node.name by the unix command
docker node ls|grep {{.Node.ID}}|awk ‘{print $2}’`

How can I input this command to the environment variable ?
for eg.,
docker service create --name xxservice -e xxenv_var=docker node ls|grep {{.Node.ID}}|awk ‘{print $2}’
(this is not working)

Can you please suggest how this can be done

Thanks.

i would do the env data creation before the docker service command…

XXenv_var=docker node ls|grep {{.Node.ID}}|awk ‘{print $2}’
docker service create --name xxservice -e xxenv_var=$XXenv_var, 

or

docker service create --name xxservice -e xxenv_var=$(docker node ls|grep {{.Node.ID}}|awk ‘{print $2}’)

I tried this, but i wonder its not recognizing {{.Node.ID}} in the below command and xxenv_var is always null

docker service create --name xxservice -e xxenv_var=$(docker node ls|grep {{.Node.ID}}|awk ‘{print $2}’)

xxenv_var={{.Node.ID}} works perfectly, but having {{.Node.ID}} inside the command is not working.

Thanks.

well, then

nodeid={{.Node.ID}}
xxenv_var=$(docker node ls|grep ${nodeid} | awk ‘{print $2}’)

This too didn’t help. Only null value is returned.

docker node ls

doesn’t return json on my manager node…

docker node inspect self

does, but there is no Node.id element.

but I think u need this from the node the service is executed on… not the manager

But since I create the service with replicas only from one host: the swarm manager, can’t get it from the node separately.

sorry, not clear what you said…

what is the output of

docker node ls

This works for me using Docker4Mac:

~ ᐅ docker node ls
ID                            HOSTNAME                STATUS              AVAILABILITY        MANAGER STATUS
t6m94lg5kl7l38orgwb9f6cfw *   linuxkit-025000000001   Ready               Active              Leader
~ ᐅ docker service create --name yy --env nodeid={{.Node.ID}} --detach nginx
hh7uko0b9ms7sl6mbrof0wyd3
~ ᐅ docker service ps yy
ID                  NAME                IMAGE               NODE                    DESIRED STATE       CURRENT STATE           ERROR               PORTS
zj4269v75ce8        yy.1                nginx:latest        linuxkit-025000000001   Running             Running 6 seconds ago
~ ᐅ docker ps | grep zj4
72c1eac4f7d0        nginx:latest        "nginx -g 'daemon of…"   16 seconds ago      Up 16 seconds       80/tcp              yy.1.zj4269v75ce8x06sizgdjtbhm
~ ᐅ docker exec -it 72c1 bash
root@72c1eac4f7d0:/# echo $nodeid
t6m94lg5kl7l38orgwb9f6cfw
root@72c1eac4f7d0:/# exit
exit
~ ᐅ

Yes, that works for me too. But, I don’t need ‘nodeid’. I need node name.
And that’s what I’m trying using below command line.
xxenv_var=$(docker node ls | grep ${nodeid} | awk ‘{print $2}’)

So instead of the below command
docker service create --name yy --env nodeid={{.Node.ID}} --detach nginx hh7uko0b9ms7sl6mbrof0wyd3
I’m trying the below ------>>>>
docker service create --name yy --env nodename=$(docker node ls | grep ${nodeid} | awk ‘{print $2}’) --detach nginx hh7uko0b9ms7sl6mbrof0wyd3

So, as you’ve connected to the container, and have $nodeid populated with the below value
root@72c1eac4f7d0:/# echo $nodeid
t6m94lg5kl7l38orgwb9f6cfw
I would like to have nodename for the respective nodeid inside the container, which is not working for me.

Hi, have you tried to add a bind volume with /etc/hostname from the host mapped in the container?

-v /etc/hostname:/etc/hostname(:ro)

Yes, I tried that. But the volume contains only one hostname of the machine from where the service is created.
But I’m creating service with --replicas=4, where 4 containers are created on 4 different machines/nodes.
So, the volume wouldn’t be useful because it has only one hostname, not each node name of the respective container.

Hi, i have tested in my environment and binding the file /etc/hostname i can get mapped in each replica the node hostname where the replica is running:

 "ContainerSpec": {
                "Image": "nginx:latest",
                "Mounts": [
                    {
                        "Type": "bind",
                        "Source": "/etc/hostname",
                        "Target": "/etc/hostname"
                    }
                ],



vidaxl@QAS-RANCHER-HOST-01:~$ sudo docker service ps testdaniel
ID                  NAME                IMAGE               NODE                  DESIRED STATE       CURRENT STATE           ERROR               PORTS
e0i4f5z0szia        testdaniel.1        nginx:latest        QAS-RANCHER-HOST-01   Running             Running 4 minutes ago                       
4l5cip628ck8        testdaniel.2        nginx:latest        QAS-RANCHER-HOST-02   Running             Running 4 minutes ago 



vidaxl@QAS-RANCHER-HOST-01:~$ sudo docker  ps | grep testda
ff889365bd26        nginx:latest                                                         "nginx -g 'daemon ..."   5 minutes ago       Up 5 minutes        80/tcp                                                testdaniel.1.e0i4f5z0sziaw5aki7x7fqi2n



vidaxl@QAS-RANCHER-HOST-01:~$ sudo docker exec -it ff889365bd26 bash
root@ff889365bd26:/# cat /etc/hostname
QAS-RANCHER-HOST-01

root@ff889365bd26:/#

And the other replica running in other host:

vidaxl@QAS-RANCHER-HOST-02:~$ sudo docker service ps testdaniel
ID                  NAME                IMAGE               NODE                  DESIRED STATE       CURRENT STATE           ERROR               PORTS
e0i4f5z0szia        testdaniel.1        nginx:latest        QAS-RANCHER-HOST-01   Running             Running 6 minutes ago                       
4l5cip628ck8        testdaniel.2        nginx:latest        QAS-RANCHER-HOST-02   Running             Running 6 minutes ago 
                      
vidaxl@QAS-RANCHER-HOST-02:~$ sudo docker ps | grep testdani
ad1876faba5a        nginx:latest                                                         "nginx -g 'daemon ..."   6 minutes ago       Up 6 minutes        80/tcp               testdaniel.2.4l5cip628ck80rpoc3ezemfuh

vidaxl@QAS-RANCHER-HOST-02:~$ sudo docker exec -it ad1876faba5a bash
root@ad1876faba5a:/# cat /etc/hostname
**QAS-RANCHER-HOST-02**

root@ad1876faba5a:/# 

Regards

Since i’m using binding volumes, docker daemon will mount the local /etc/hostname in each replica.
So each replica will have mounted the hostname file of the node where it is running:

Regards

You’re absolutely right!
I could get the node hostname in each replica container. I tried this before also, but somehow I didn’t make it work. Now its working as I needed.
Thanks a lot !

What would really be nice is if you could get the hostname to be the taskname, so in your containers example above the hostnames would be testdaniel.1 and testdaniel.2. Anyone have ideas about how to accomplish this?