Compose: Service can't be reached by defined hostname

Created on 15 Feb 2016  ยท  33Comments  ยท  Source: docker/compose

Given the following docker-compose.yml file:

version: '2'

networks: 
  mynet:
    driver: bridge

services:

  master:
    image: busybox
    command: top
    hostname: amasterservice
    networks: 
      - mynet

  slave: 
    image: busybox
    command: top
    networks:
      - mynet

The following ping fails:

$ docker exec -ti test_slave_1 ping amasterservice
ping: bad address 'amasterservice'
arenetworking kinenhancement

Most helpful comment

If goal of Docker Compose is to make it easier for users to deploy a composition of services using Docker images and containers, then the file definition should be crystal clear.

When a user defines a hostname to a service, it will expect that hostname to be resolvable from other services, specially when these services participate in the same network (as per my example).

Since a service can have multiple instances, it is just logical that when I define a hostname to a service, that hostname resolves to multiple instances (thus using the new DNS feature in latest version).

If nothing of these can be implemented today, or should not be implemented at all, then it is a matter of clarifying the documentation to state either:

  1. hostname should have restriction like container_name where one service instance only will exist.
  2. hostname should not be allowed in the compose file because there is no value added to that rather creating confusion in users' mind.

All 33 comments

Adding depends_on (in slave to master) does not fix the problem.

Looking at docker inspect test_master_1, I see two aliases:

...
"Aliases": [
    "master",
    "268ef7e1e5"
],
...

The first comes from the service name, and the second is the container's short ID. I think that by default Compose doesn't create aliases based on hostnames.

May I ask what you're trying to accomplish? Why can't the hostname also be "master", and why does the slave need to ping the master by hostname rather than by service name?

Hi @jake-low, I think question is why isn't hostname defined under aliases. What is the reasoning behind this decision?

My guess would be because hostname isn't guaranteed to be unique, and aliases are required to be. How would Compose handle this situation?

version: '2'
services:
  foo:
    image: busybox
    command: top
    hostname: notunique
  bar: 
    image: busybox
    command: top
    hostname: notunique
  test:
    image: busybox
    command: ping notunique

Service name and container ID are both guaranteed to be unique -- service because YAML doesn't allow multiple keys with the same name, and container ID because Docker uses a unique hash automatically.

There was some discussion early on about using hostname instead of container_name as the default name used by docker, but that didn't happen (I'm not sure why).

We add aliases for service name and short id to be backwards compatible and handle the common use cases. We're also adding support for your own net-aliases in #2829

As far as I know, it's not all that uncommon for the internal hostname to be unresolvable from the outside.

We could probably make it another alias, but I'm not sure how we'd deal with conflicts with the service names.

This may be a decision better left to the Engine team, as there's currently an incongruity there that needs to be solved.

When you run a container with docker run, no alias gets created for it. However, if you give it a --name, both its hostname (a random SHA) and its container name are resolvable.

It's strange that, even though Docker gives every container a unique ID and nickname, neither is by default DNS-resolvable (based on my tests; someone feel free to correct me).

As a Docker Composer user, I expect that whenever I set a hostname to a service, that hostname should resolve to _any_ instance of that service. Same should apply for the service name.

If these things should not work the same way, and a user should only rely on service name, then hostname definition should not be allowed in the compose file. It just creates confusion.

That's a tall order. DNS load balancing is crude and has many unusual failure cases due to DNS's hierarchical organization and client caching behaviour [1]. This is why application-level (so-called Layer 7) load balancing schemes have become popular [2].

Tutum provides DNS-level load balancing (mapped to services, not hostnames), as seen here (last paragraph), but as the rest of the article discusses, this feature is recommended for use as a second-level load balancer. Primary load balancing duties have been assigned to a purpose-built container.

If goal of Docker Compose is to make it easier for users to deploy a composition of services using Docker images and containers, then the file definition should be crystal clear.

When a user defines a hostname to a service, it will expect that hostname to be resolvable from other services, specially when these services participate in the same network (as per my example).

Since a service can have multiple instances, it is just logical that when I define a hostname to a service, that hostname resolves to multiple instances (thus using the new DNS feature in latest version).

If nothing of these can be implemented today, or should not be implemented at all, then it is a matter of clarifying the documentation to state either:

  1. hostname should have restriction like container_name where one service instance only will exist.
  2. hostname should not be allowed in the compose file because there is no value added to that rather creating confusion in users' mind.

We should probably add a warning to the docs about using hostname. I think it is rarely useful.

We should probably add a warning to the docs about using hostname. I think it is rarely useful.

I think it should not be allowed at all.

That is not backwards compatible, and while it is "rarely" useful, there are still cases where it is useful in its current form, so removing it completely is not really an option.

That is not backwards compatible, and while it is "rarely" useful, there are still cases where it is useful in its current form, so removing it completely is not really an option.

Then the feature should work as expected by users using Compose for the first time, by adding that information to the list of alises.

Could you please be more specific where, although rare, the current form is useful?

That is not backwards compatible, and while it is "rarely" useful, there are still cases where it is useful in its current form, so removing it completely is not really an option.

Agreed; I use it in a couple of cases where legacy applications expect to be able to resolve themselves by their own hostname (in these cases matching hostname to the service name in the composition).

I've also used it in Kerberos environments, when the hostname on a host needs to be set to an FQDN (not necessarily unique) so that services running there can use their service principals to authenticate themselves.

IMHO this feature does work "as expected" because it works the same way it does in Docker engine. Running a container with the --hostname argument does one thing: sets the hostname. Aliases are defined by the user (with the caveat I mentioned earlier).

IMHO this feature does work "as expected" because it works the same way it does in Docker engine. Running a container with the --hostname argument does one thing: sets the hostname. Aliases are defined by the user (with the caveat I mentioned earlier).

Not really. With overlay network, the hostname set in a container is reachable by another container. So I disagree that it works as "expected". In fact, what users expect (and think about new users), is that when a hostname is set, specially in the case of Docker Compose, that hostname can be used by other containers.

With overlay network, the hostname set in a container is reachable by another container.

That's not true.

$ docker run -d --hostname testing --net my_overlay_network alpine sleep 300
12e9d172d1964c2ad843f3bb4b61556eb75c0680ec95d8559fe77e617cf1371b
$ docker run --rm --net my_overlay_network alpine ping testing
ping: bad address 'testing'

What you're saying is true if you set the --name of the container, not the --hostname.

$ docker run -d --name testing --net my_overlay_network alpine sleep 300
ac8ec87ec8c2893588a8d271401deb07ca934d3d5590e6726ea17cea5166876e
$ docker run --rm --net my_overlay_network alpine ping testing
PING testing (10.0.9.3): 56 data bytes
64 bytes from 10.0.9.3: seq=0 ttl=64 time=0.525 ms
64 bytes from 10.0.9.3: seq=1 ttl=64 time=0.495 ms
64 bytes from 10.0.9.3: seq=2 ttl=64 time=0.590 ms
^C
--- testing ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.495/0.536/0.590 ms

Proof that this is a swarm, and an overlay network:

$ docker network inspect my_overlay_network
[
    {
        "Name": "my_overlay_network",
        "Id": "102259bd950d46e3d3b1694f09708dc3833d4cda80a525cde1fbd081ce5bbabd",
        "Scope": "global",
        "Driver": "overlay",
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.9.0/24"
                }
            ]
        },
        "Containers": {
            "1c1609f004bff373d2c26dd269d37411214bfb05c73607620bab286621585d27": {
                "Name": "testing",
                "EndpointID": "c2c5b645e36b52952f7744d02030b3e06e1637a781be55a93ab2eebb63849429",
                "MacAddress": "02:42:0a:00:09:02",
                "IPv4Address": "10.0.9.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]
$ docker info
Containers: 5
 Running: 4
 Paused: 0
 Stopped: 1
Images: 4
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 mhs-demo0: 192.168.99.102:2376
  โ”” Status: Healthy
  โ”” Containers: 3
  โ”” Reserved CPUs: 0 / 1
  โ”” Reserved Memory: 0 B / 1.021 GiB
  โ”” Labels: executiondriver=native-0.2, kernelversion=4.1.17-boot2docker, operatingsystem=Boot2Docker 1.10.1 (TCL 6.4.1); master : b03e158 - Thu Feb 11 22:34:01 UTC 2016, provider=virtualbox, storagedriver=aufs
  โ”” Error: (none)
  โ”” UpdatedAt: 2016-02-17T01:32:30Z
 mhs-demo1: 192.168.99.103:2376
  โ”” Status: Healthy
  โ”” Containers: 2
  โ”” Reserved CPUs: 0 / 1
  โ”” Reserved Memory: 0 B / 1.021 GiB
  โ”” Labels: executiondriver=native-0.2, kernelversion=4.1.17-boot2docker, operatingsystem=Boot2Docker 1.10.1 (TCL 6.4.1); master : b03e158 - Thu Feb 11 22:34:01 UTC 2016, provider=virtualbox, storagedriver=aufs
  โ”” Error: (none)
  โ”” UpdatedAt: 2016-02-17T01:32:04Z
Plugins: 
 Volume: 
 Network: 
Kernel Version: 4.1.17-boot2docker
Operating System: linux
Architecture: amd64
CPUs: 2
Total Memory: 2.043 GiB
Name: mhs-demo0

@jake-low indeed, thanks for checking. I missed that I was setting --name too on my shell scripts.

Any update on this issue?

It's long been an annoyance for me that compose only creates the DNS container name aliases when using docker-compose up, and not when using docker-compose run.

The --name trick solves it, but it feels like this shouldn't be necessary.

compose only creates the DNS container name aliases when using docker-compose up, and not when using docker-compose run.

This burnt almost 2 days of development on my end (with very cryptic failures).

Do you by chance know if docker-compose exec is also affected?

May I ask what is the best practice to resolve this hostname resolving issue in 2018? Should hostname be specified in the compose file?

@slothkong

I solved this problem. When using driver: bridge, I use the --add-host hostname:172.x.x.x parameter in the docker run command.

The docker run needs to specify the IP (--ip) and network name (--net) for the container.

@slothkong
Also, do not mistake to refer service name not image name (as I did :-( ):

    mongodb:
        image: mongo

Mistake: MONGODB_URL=mongodb://mongo:27017
Correct: MONGODB_URL=mongodb://mongodb:27017

After using docker for years, this docker-compose bug is a surprise.

docker run --hostname myhostname --name myname --network=mybridgenetwork --rm myimage

and as expected the container is resolvable on somebridgenetwork by myhostname but not myname on the network

Surprisingly, in docker-compose, the container would be resolvable by myname but not myhostname on the network.


Side note: These are two different concepts: container names are meant for container management and scoped to a Docker instance, hostnames are meant for network management and scoped to a network.

@slothkong
Also, do not mistake to refer service name not image name (as I did :-( ):

    mongodb:
        image: mongo

Mistake: _MONGODB_URL=mongodb://mongo:27017_
Correct: _MONGODB_URL=mongodb://mongodb:27017_

thanks bro))

What is the last solution to dns resolve for services with hostname or domainname in the same compose file ????

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Still doesn't work...

This issue has been automatically marked as not stale anymore due to the recent activity.

activity occurs

This unexpected behavior still exists. The best solution I have found is this SO answer

It's year 2020 and the issue seems to persist still. I need hostname with domainname to work. This is NOT a feature but a bug!!!
Docker-compose version 3.4

Containers are spun up by docker-compose up.

ambari-server:
    image: hdp/ambari-server
    networks:
     - dev
    hostname: ambari
    domainname: dev
...   

works:

  • can be pinged by service name from other containers. i.e, ambar-server
  • can ping itself by service name, i.e. ambari-server
  • hostname command returns the set hostname. i.e. ambari
  • can ping itself by <hostname>.<domainname> , i.e. ambari.dev

doesn't work:

  • can not be reached from other container by <hostname>.<domainname>, i.e. ambari.dev
  • can not be reached from ohter container by <hostname>, i.e. ambari

A work around is to use <hostname>.<domainname> as the service name but this brings out a whole bunch of other issues, e.g. this is not allowed in swarm-kit (https://github.com/docker/swarmkit/issues/2437)

I think the following summarizes the design philosophy and the solution to this problem:

1> the hostname, domainname tag is for modifying the hosts file. It doesn't help with dns resolution except to the container itself.
2> using network aliases are the recommended solutions. You have to add it to every container but that seems to be most straightforward way to solve the problem.
3> container name as a matter fact can be thought of just another network alias.

It's year 2020 and the issue seems to persist still. I need hostname with domainname to work. This is NOT a feature but a bug!!!
Docker-compose version 3.4

Containers are spun up by docker-compose up.

ambari-server:
    image: hdp/ambari-server
    networks:
     - dev
    hostname: ambari
    domainname: dev
...   

works:

* can be pinged by service name from other containers. i.e, ambar-server

* can ping itself by service name, i.e.  ambari-server

* hostname command returns the set hostname.  i.e. ambari

* can ping itself by `<hostname>.<domainname>` , i.e. ambari.dev

doesn't work:

* can not be reached from other container by  `<hostname>.<domainname>`, i.e. ambari.dev

* can not be reached from ohter container by `<hostname>`, i.e. ambari

A work around is to use <hostname>.<domainname> as the service name but this brings out a whole bunch of other issues, e.g. this is not allowed in swarm-kit (docker/swarmkit#2437)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dazorni picture dazorni  ยท  3Comments

saulshanabrook picture saulshanabrook  ยท  3Comments

bergtwvd picture bergtwvd  ยท  3Comments

squeaky-pl picture squeaky-pl  ยท  3Comments

foxx picture foxx  ยท  3Comments