Skip to content

Docs: Compose ports default binding IP + multiple network with host_binding_ipv4 set #12616

Description

@polarathene

Description

TL;DR:

  • A service will default to 0.0.0.0 for host binding, unless the network itself has configured host_binding_ipv4.
  • If a service has more than one such network, only one network is chosen for host binding default address. This appears to at least prioritize via sorting by the network name attribute.
  • The implicit default network could be improved (see 2nd section).

This might be worth documenting under the ports section? That presently states the default binding is 0.0.0.0 if no explicit host IP is provided, which is true unless something else would have altered that elsewhere.

I have seen a pattern to configure a default network to override the implicit default bridge network created for a compose project. I've also seen usage of host_binding_ipv4 to change from 0.0.0.0 to say 127.0.0.1 and have this the implicit default for all published service ports in the compose project (assuming the containers use the implicit default network).

name: example

services:
  hello:
    image: alpine
    init: true
    command: sleep 60
    ports:
      - "1234:80" # bound to 127.0.0.42 (default / example-a)
    networks:
      - custom-net
      - default # Specifying `networks` removes implicit default to `default` network, add it back

  world:
    image: alpine
    init: true
    command: sleep 60
    ports:
      - "5678:80" # bound to 127.0.0.1 (custom-net / example-b)
    networks:
      custom-net:
        aliases:
          - hello.world.internal

networks:
  default:
    name: example-a # alphanumerically this has priority
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: 127.0.0.42

  custom-net:
    name: example-b
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: 127.0.0.1
docker compose up -d --force-recreate
docker compose ps

NAME                COMMAND             SERVICE             STATUS              PORTS
example-hello-1     "sleep 60"          hello               running             127.0.0.42:1234->80/tcp
example-world-1     "sleep 60"          world               running             127.0.0.1:5678->80/tcp

I was curious however what this behaviour would be when there are multiple networks assigned to a container. Would it default to publishing to both of these IP on the host, or only 1? Documentation seems to be lacking.

When experimenting, I came to find that it only binds to one, but how that was decided or sorted was unclear. In this case it seems to be done via the name attribute with alphanumeric sort.

I don't know how reliable of an expectation that is.

  • Is it something the spec should cover? (I haven't checked, but based on the lack of associated user-facing docs, I'm guessing this is up to the implementor and thus may not be consistent)
  • Will Docker Compose v2 reliably behave this way, or is it risky and each service published port should have an explicit mapping, especially ones with more than one network attached?

There is networks.<network>.priority, but this has no influence on the bind behaviour either.


default network documentation is a tad sparse/vague

Docs also don't really seem to clarify that you can either have networks as a list of strings for networks, or each network as object keys, but not a list of objects (which will error when attempting to use that).

The services top-level page only ever mentions the default network (created implicitly by Compose, when the user doesn't configure a default network explicitly) in the links attribute docs.

This is briefly described on the top-level Networks page, but not that the network is literally default, or that you can override it while having all services in the compose project conveniently use that by default.

The networks top-level page does casually show default network in use under each services networks attribute for the external example (despite default itself not having much to do with that, only one service needed that to use outside + implicit default, but with no context to the reader).

Probably value in better documentation for this network. It can be quite beneficial to users for small changes (less relevant now for IPv6 support IIRC), so having better visibility / awareness in service top-level networks attribute docs would be good?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions