94

What are the ways get the docker host's hostname from inside a container running on that host besides using environment variables? I know I can pass the hostname as an environment variable to the container at container creation time. I'm wondering how I can look it up at run time.

foo.example.com (docker host)
  bar (docker container)

Is there a way for container bar running in docker host foo.example.com to get "foo.example.com"?

Edit to add use case:

The container will create an SRV record for service discovery of the form

_service._proto.name. TTL class SRV priority weight port target.
-----------------------------------------------------------------
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo.example.com.

where 20003 is a dynamically allocated port on the docker host for a service listening on some fixed port in bar (docker handles the mapping from host port to container port).

My container will run a health check to make sure it has successfully created that SRV record as there will be many other bar containers on other docker hosts that also create their own SRV records.

_service._proto.name. TTL class SRV priority weight port target.
-----------------------------------------------------------------
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo.example.com. <--
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo2.example.com.
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo3.example.com.

The health check will loop through the SRV records looking for the first one above and thus needs to know its hostname.

aside

I'm using Helios and just found out it adds an env var for me from which I can get the hostname. But I was just curious in case I was using docker without Helios.

David Xia
  • 5,075
  • 7
  • 35
  • 52
  • Could you please clarify, why do you need this feature? – Vitaly Isaev Apr 22 '15 at 21:37
  • Perhaps if you could explain your use-case there might be a better approach to your problem? – James Mills Apr 22 '15 at 23:25
  • 1
    @VitalyIsaev added use case – David Xia Apr 23 '15 at 00:24
  • Another use case where this comes up: if you want to use Docker to containerize Erlang deployments, but have what's acting inside the docker container act to the outside world as if it were the host. In this case, you want the erlang node to have a nodename that matches the host's. – James Kingsbery Aug 06 '15 at 19:58
  • @DavidXia - thanks for sharing info on Helios ... on another similar service called DockerCloud (previously known as Tutum), the added env variables are `DOCKERCLOUD_CONTAINER_HOSTNAME` and `DOCKERCLOUD_CONTAINER_FQDN` – pulkitsinghal Mar 17 '16 at 20:46
  • Related: [How to specify hostname for the running container?](https://serverfault.com/q/590191/130437) – kenorb Feb 14 '19 at 23:38
  • 4
    Unfortunately the [best answer](https://stackoverflow.com/a/51894801/1948292) got deleting... simply use `host.docker.internal `. – Daniel W. Feb 25 '20 at 15:19
  • `host.docker.internal` only works on development machines (Docker4Win, Docker4Mac), not on real linux production machines. – Marcus K. May 23 '21 at 14:40

12 Answers12

40

You can easily pass it as an environment variable

docker run .. -e HOST_HOSTNAME=`hostname` ..

using

-e HOST_HOSTNAME=`hostname`

will call the hostname and use it's return as an environment variable called HOST_HOSTNAME, of course you can customize the key as you like.

note that this works on bash shell, if you using a different shell you might need to see the alternative for "backtick", for example a fish shell alternative would be

docker run .. -e HOST_HOSTNAME=(hostname) ..
Mohammad AbuShady
  • 40,884
  • 11
  • 78
  • 89
  • 10
    I was wondering if there's a way to do this without using env vars. – David Xia Apr 23 '15 at 04:11
  • 3
    Unfortunately the environment variable approach doesnt work when using an `.env` file with `docker-compose`, but you CAN use `$HOSTNAME` in the `environment:` section. – mkst Nov 05 '19 at 17:24
30

I'm adding this because it's not mentioned in any of the other answers. You can give a container a specific hostname at runtime with the -h directive.

docker run -h=my.docker.container.example.com ubuntu:latest

You can use backticks (or whatever equivalent your shell uses) to get the output of hosthame into the -h argument.

docker run -h=`hostname` ubuntu:latest

There is a caveat, the value of hostname will be taken from the host you run the command from, so if you want the hostname of a virtual machine that's running your docker container then using hostname as an argument may not be correct if you are using the host machine to execute docker commands on the virtual machine.

GordonM
  • 31,179
  • 15
  • 87
  • 129
  • 2
    This is the best answer, since it will modify output of the `uname` system call. By that it will work with `hostname` program or other C written programs such as Python's `socket.gethostname()`. Changing `HOSTNAME` environmental variable or mounting `/etc/hostname` to container will not do that. – Majus Misiak Jul 12 '19 at 06:13
29

You can pass in the hostname as an environment variable. You could also mount /etc so you can cat /etc/hostname. But I agree with Vitaly, this isn't the intended use case for containers IMO.

seanmcl
  • 9,740
  • 3
  • 39
  • 45
  • 1
    mounting /etc is probably the easiest or some other data directory that you store this value in, so as to not expose the entire /etc dir. Instead create `~/data/hostname` and share ~/data – Michael Apr 23 '15 at 00:17
  • The use case that led me here was creating a password reset link. – jxstanford Nov 14 '15 at 01:15
  • Varnish creates a directory with the container hostname like: `/usr/local/var/varnish/a15daa0160c8/` – guneysus Mar 29 '16 at 08:59
  • 211
    Comments like "it's hard to imagine why you want this" are unhelpful and rude. For sure, starting with a green field, this request doesn't fit the intended model of containerization. But there are easily imaginable cases where you might want to send a network request from a service inside one container to a service on the host machine. Perhaps you're working on slowly, methodically migrating from a monolith running locally to microservices running in containers. This is my current challenge and googling for a solution brought me here. – Adam Tuttle Sep 12 '16 at 17:46
  • 43
    Ack. Thanks for the constructive criticism. – seanmcl Sep 12 '16 at 17:54
  • 25
    My use case is writing to a log machine and wanting to know which physical host it came from when I have the same app running in containers on multiple physical hosts – Charlie Martin Jun 16 '17 at 00:19
  • 3
    Not having to add extra parameters is better than having to add extra parameters when running docker. That is my use case. – nurettin Jan 23 '19 at 08:25
  • 3
    In my case, I want to create AWS alarms automatically and I need the hostname of the host or AWS won't know what I'm talking about. – Pablo D. Jul 09 '19 at 12:35
  • 2
    I want to tag builds which are allocated randomly to one node in a cluster with the hostname that built them. To help debugging various issues. – Ed Randall Nov 29 '19 at 19:22
  • In my use case I want to add the docker host's hostname as a logging parameter to clarify exactly where the container was running at the time of logging – Stephan Møller Nov 30 '20 at 11:53
  • I like this answer because it also works with docker-compose. – Trayan Momkov Feb 07 '22 at 11:35
  • it's good to know: `host.docker.internal` -- that was mentioned by daniel-w before -- it may not work in all environments but there is a big change you need this feature in a development environment where it is available. Use case for those who say this is wrong: I am debugging a service on my local machine (host), which is used by a container. I just point the container to my local machine. – droperto Aug 31 '22 at 03:28
  • @seanmcl One use case for this, the reason I found this post, I am setting up letsencrypt and want to use the name of the host its running on to generate the certificate name. – Nick W. Jun 29 '23 at 20:19
8

Another option that worked for me was to bind the network namespace of the host to the docker.

By adding:

docker run --net host
azDev
  • 399
  • 5
  • 10
  • 2
    could you clarify your answer? with respect to the poster's original question, are you suggesting that he run `docker run --net host bar`? – ekkis Mar 16 '17 at 19:44
  • 2
    The command will actually be `docker run --net=host`. Notice the `=` sign. – Astitva Srivastava Jun 11 '19 at 05:23
  • 1
    Just be aware of caveats. Running `--network=host` has a lot of other implications. It might or might not work well for specific system. (I'm actually using it for one system for entirely different reasons). Also, it is Linux-specific and would not work on Mac or Windows. – Dima Korobskiy Feb 26 '21 at 22:05
8

You can pass it as an environment variable like this. Generally Node is the host that it is running in. The hostname is defaulted to the host name of the node when it is created.

docker service create -e 'FOO={{.Node.Hostname}}' nginx  

Then you can do docker ps to get the process ID and look at the env

$ docker exec -it c81640b6d1f1 env                                                                                                                                    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=c81640b6d1f1
TERM=xterm
FOO=docker-desktop
NGINX_VERSION=1.17.4
NJS_VERSION=0.3.5
PKG_RELEASE=1~buster
HOME=/root

An example of usage would be with metricbeats so you know which node is having system issues which I put in https://github.com/trajano/elk-swarm:

  metricbeat:
    image: docker.elastic.co/beats/metricbeat:7.4.0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro
      - /proc:/hostfs/proc:ro
      - /:/hostfs:ro
    user: root
    hostname: "{{.Node.Hostname}}"
    command:
      - -E
      - |
        metricbeat.modules=[
          {
            module:docker,
            hosts:[unix:///var/run/docker.sock],
            period:10s,
            enabled:true
          }
        ] 
      - -E
      - processors={1:{add_docker_metadata:{host:unix:///var/run/docker.sock}}} 
      - -E
      - output.elasticsearch.enabled=false
      - -E
      - output.logstash.enabled=true
      - -E
      - output.logstash.hosts=["logstash:5044"]
    deploy:
      mode: global
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265
  • 5
    Placeholders like `.Node.Hostname` are documented at https://docs.docker.com/engine/reference/commandline/service_create/#create-services-using-templates – Mark Rajcok Jul 24 '20 at 16:53
  • This doesn't work in docker compose. The hostname is actually {{.Node.Hostname}} instead of the placeholder value. – Ebsan Aug 17 '22 at 19:37
  • I found that on windows I had to use interpolation and the $COMPUTERNAME environment variable. (https://docs.docker.com/compose/compose-file/#interpolation) – Ebsan Aug 17 '22 at 19:45
7

OK, this isn't the hostname (as OP was asking), but this will resolve to your docker host from inside your container for connectivity purposes.

host.docker.internal

I was redirected here when googling for this.

Phil
  • 1,996
  • 1
  • 19
  • 26
5

I think the reason that I have the same issue is a bug in the latest Docker for Mac beta, but buried in the comments there I was able to find a solution that worked for me & my team. We're using this for local development, where we need our containerized services to talk to a monolith as we work to replace it. This is probably not a production-viable solution.

On the host machine, alias a known available IP address to the loopback interface:

$ sudo ifconfig lo0 alias 10.200.10.1/24

Then add that IP with a hostname to your docker config. In my case, I'm using docker-compose, so I added this to my docker-compose.yml:

extra_hosts:
# configure your host to alias 10.200.10.1 to the loopback interface:
#       sudo ifconfig lo0 alias 10.200.10.1/24
- "relevant_hostname:10.200.10.1"

I then verified that the desired host service (a web server) was available from inside the container by attaching to a bash session, and using wget to request a page from the host's web server:

$ docker exec -it container_name /bin/bash
$ wget relevant_hostname/index.html
$ cat index.html
Adam Tuttle
  • 19,505
  • 17
  • 80
  • 113
  • Thanks for this, I read through the docker issues and this is my preferred solution for a docker-compose project – ebrohman Apr 21 '17 at 18:45
0
 HOSTIP=`ip -4 addr show scope global dev eth0 | grep inet | awk '{print $2}' | cut -d / -f 1 | sed -n 1p`
 docker run  --add-host=myhost:${HOSTIP} --rm -it debian

Now you can access the host under the alias "myhost"

The first line won't run on cygwin, but you can figure out some other way to obtain the local IP address using ipconfig.

xpusostomos
  • 1,309
  • 11
  • 15
0

you can run:

docker run --network="host"

for sending the value of the machine host to the container.

morpheus
  • 19
  • 2
0

You can pass the --uts=host flag to set the hostname in the container

Before

➜  ~ docker run -it busybox
/ # cat /etc/hostname
bf260c9f082b
/ # hostname
bf260c9f082b

After

➜  ~ docker run -it --uts=host busybox
/ # cat /etc/hostname
e63de0410791
/ # hostname
hh

Docs: https://docs.docker.com/engine/reference/run/#uts-settings---uts

Bob
  • 689
  • 10
  • 11
-1

I ran

docker info | grep Name: | xargs | cut -d' ' -f2

inside my container.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
-2

I know it's an old question, but I needed this solution too, and I acme with another solution.

I used an entrypoint.sh to execute the following line, and define a variable with the actual hostname for that instance:

HOST=`hostname --fqdn`

Then, I used it across my entrypoint script:

echo "Value: $HOST"

Hope this helps

Reinaldo
  • 377
  • 3
  • 7