compose
compose copied to clipboard
Setting container hostname to `service_name-xx` instead of container-id
For this sample compose file
services:
my-app:
image: my-image:0.1
his-app:
image: his-image:0.1
Compose creates my-app-1 container for my-app with host-name as container-id say rndmcntrid
This container is reachable from other services like his-app-1 with my-app, my-app-1 or rndmcntrid.
Can we have compose set container hostname as service-1? e.g. in case of my-app above, hostname be set to my-app-1 instead of rndmcntrid
Docker Compose version v2.10.2
Set the hostname field. See the docs for details: https://docs.docker.com/compose/compose-file/#hostname
services:
my-app:
image: my-image:0.1
hostname: my-app-1
his-app:
image: his-image:0.1
Oops! The description I gave made it look as 'question: how to set hostname for container' while what wanted was:
Is it possible to enhance compose to set hostname to my-app-1 for containers without explicit hostname configuration in compose file, instead of container-id.
And in case of multiple replicas set as my-app-1, my-app-2 etc. for the replicas.
Ah, ok, I'll re-open and mark this as a feature request.
Is there a specific reason that the built-in name resolution is inadequate and you want the hostname explicitly set? Trying to understand the use case here.
Thanks @milas.
Explanation follows, but before that would like to mention that this may be a specific use case, as I have not much idea if there are other systems, that rely on hostname like rabbitmq.
Came across this when trying to cluster rabbitmq using its classic peer discovery, using compose.
RabbitMQ configuration
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@rabbit_1
cluster_formation.classic_config.nodes.2 = rabbit@rabbit_2
rabbit_1, rabbit_2 should be hostnames of the rabbit instances. Doesn't work with alias app-rabbit-1 or service name if hostname is not explicitly set.
compose file 2 services with explicit hostname.
# compose project name = app
rabbit-1:
image: rabbitmq:management-alpine
hostname: "rabbit_1"
rabbit-2:
image: rabbitmq:management-alpine
hostname: "rabbit_2"
For 2 instances 2 services, for 5 instances 5 service definitions. No benefit of scaling can be taken here.
If compose could set hostname app-rabbit-1, app-rabbit-2 etc. then rabbit service could be declared as
# compose project name = app
rabbit:
image: rabbitmq:management-alpine
deploy:
replicas: 3
And peer discovery configured as
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@app-rabbit-1
cluster_formation.classic_config.nodes.2 = rabbit@app-rabbit-2
cluster_formation.classic_config.nodes.3 = rabbit@app-rabbit-3
We can use app-rabbit-X as hostnames in config in this case, because we know compose will set hostname for containers as that.
Also this opens up option for scaling.
Awesome, thanks so much for the detailed explanation!
I can't guarantee we will take this feature, but having well-defined use cases helps us prioritize requests.
For anyone else who has reached this issue and is interested, please use the 👍 reaction on the main issue. If you have other use cases not covered, please feel free to comment as well.
Some possible implementation notes:
As of now, this is what the spec has to say on hostname:
hostnamehostnamedeclares a custom host name to use for the service container. MUST be a valid RFC 1123 hostname.
Arguably, this is already underspecified for usage with replicas.
At a first glance, I'd say we should he appending the replica # (if > 1) to the custom hostname (if provided) to prevent duplicates.
Then you could set something like hostname: foo- to get foo-1, foo-2, etc.
Any bigger change (e.g. to allow a templating variable, maybe similar to mktemp?) would likely necessitate a bigger spec update/change rather than clarification/amendment.
@milas the issue is closed, could you please re-open it.
Sorry for interrupt, but maybe ability to set a pattern for hostname may solve the problem? Thats actually a question which i goggled for and found this issue:
- is there a way to generalize hostname value in templates, e.g.
x-templates:
common: &x-common
env_file: .env
hostname: 'my-{{ .Service.Name }}'
# etc.
services:
service1:
<<: *x-common
# etc.
service2:
<<: *x-common
# etc.
service3:
<<: *x-common
# etc.
and get as a result service1 with my-service1 hostname, service2 with my-service2, etc. ?
Some kind of "helmy" templating, i would say
We really, really don't want to introduce a templating language inside the compose file format
@milas we indeed could compute hostname as container is created with some custom, dedicated logic for this use-case
Hostname: strings.Replace(service.Hostname,"XXX", number)
I wonder which character to use to prevent any side effet, and make it clear a replacement will take place here (as I can guess we will get requests to support this in a few other places)
I ran a quick test:
services:
base:
image: nginx
scale: 2
master:
image: alpine
command: ping localhost
ran the stack then exec into my "master" node:
docker compose exec master ash
/ # ping chose-base-1
PING chose-base-1 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.258 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.425 ms
^C
--- chose-base-1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.258/0.341/0.425 ms
/ # ping chose-base-2
PING chose-base-2 (172.18.0.5): 56 data bytes
64 bytes from 172.18.0.5: seq=0 ttl=64 time=0.573 ms
64 bytes from 172.18.0.5: seq=1 ttl=64 time=0.419 ms
^C
--- chose-base-2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.419/0.496/0.573 ms
service container is registered on network with alias {{project-service-replica}} you can use for service discovery as requested, without any additional configuration or explicit hostname
just a quick note that container index might not start by 1. If for some reason you delete service_replica_1 and run another docker compose up, a new container will be created to match the requested scale but as service_replica_n+1
not now it is supported natrually?
Do you have a use case for this feature you could describe here ? As container is connected to network with service alias, I wonder why setting hostname as requested would be useful
Here's the scenario: We have a Master Node communicating with Slave Nodes (Host).
In most cases, cluster software is designed as a single process. Sometimes it utilizes all hardware resources, but often there are times when it's blocked(Networking, IO, Sync.... etc).
Here's the structure: Master Node -> [Docker Compose (Host Machine)] -> Slave Nodes (Container).
In this setup, Docker Compose acts as an intermediate level manager node. However, there's no information about the original software's host machine. So, I'd like to add metadata to the slave nodes regarding their host machine.
For example:
Host1-1 Host1-2 Host1-3 Host1-4
Host2-1 Host2-2 Host2-3 Host2-4
Of course, this can be achieved through scripting, but it's a bit complex.
(I have already solved this problem... just using scripting.)
I think if Docker Compose supported more systemable environment variables(like service name, replica index, etc...), it would simplify the problem. (Almost the way is good. of course, more complex things have to use theres way)
IIUC you'd like to get some metadata in container to let you know about the service and replica number being ran. Can you please describe how you would use this, and why this can't just be achieved by external monitoring (which has easy access to container labels)?
Perhaps this could use the templating option as they're supported by swarm services https://docs.docker.com/engine/reference/commandline/service_create/#create-services-using-templates
before considering feasability and syntax to support this, I'd like to understand the benefits having such a feature. Actually I'd prefer we get a generic introspection mechanism for a container to know about it's usage context, I would typically suggest we rely on the legacy /.dockerenv file created at all containers root (for legacy reason IIUC) or something comparable
Yeah, introspection is a topic that returns frequently, but still needs a lot of thinking. The templating options mean that the user remains in control over what information "leaks" into the container. (There were some (probably similar) use-cases for users running swarm-services).
I agree that we should have a good understanding of use-cases before committing to anything (but thought I'd comment the suggestion so that IF we would consider, we could re-use existing principles, instead of creating something new "from scratch').
Actually I am trying to use Azure Pipeline Agent on Host machine, the agent is designed to perform 1 task at 1 time. So I run this with docker compose. 1 host machine, 4 agent docker containers. If some agent dies, then I have to check the agent is where on it.
@dbwodlf3 are you running those agents as replicas for a single service? How would hostname help you managing a died agent? Don't you just restart it with compose up?
Closing this feature request as "not planed" as there's no clear use-case requiring such a change. Feel free to open a follow-up issue if you have one you can share
@ndeloof, please close again as not planned. The purple colors indicate that it is closed as done.
@ndeloof could you please reopen this? The author put a very good description of the use case he (and I) are trying to solve with rabbitmq as an example. I think the discussion got a little distracted.
IMHO it could be solved with a setting in the deploy section something like "set-hostname: true" which set the hostname of each node.
@womblep as commented on https://github.com/docker/compose/issues/9858#issuecomment-1829316742 replicas can be accessed as <service>-<replica> and setting host name wouldn't help from this use-case
@ndeloof yes setting the hostname does help. RabbitMQ expects that the reverse-dns name is the same as the hostname to be able to resolve cluster members when setting up the cluster using the DNS peer discovery protocol. The process is:
- Create the node name using the hostname
- get the A record used to discover peers (with docker compose the setting deploy->endpoint_mode= dnsrr works)
- With each IP address contact the peer and get it's node name then do a reverse-DNS on the IP address and see if the 2 match (with docker they dont)
- Only if they match will the peer be used
@womblep that's a weird requirement by rabbitmq, is this documented anywhere ?
According to https://www.rabbitmq.com/docs/cluster-formation#peer-discovery-dns there's no "see if the 2 match" constraint you describe I also can see there are alternative peer discovery plugins for cloud infrastructures (kubernetes, aws ..) which could also be useful for a compose deployment (https://github.com/rabbitmq/rabbitmq-server/tree/main/deps/rabbitmq_peer_discovery_consul)