Why can two containers on one host both listen on port 8080 without the second bind failing?
answer
- port numbers are scoped, not machine-wide
- each view owns a port space
- same number, different view
- one view means one bind per port
- address distinguishes, so numbers may repeat
basics
~20 sA port number is scoped to a network view, not to the machine. Each container normally has its own view and therefore its own port space, so port 8080 in one is a different port from 8080 in the other.
solid answer
~40 sBinding a port claims that number inside one port space, and each container's private network view carries a port space of its own. Twenty containers on one host can each bind 8080 and none of them conflict, because the number is only unique per view. Collisions come back the moment the port space is shared: two containers placed in **one shared network view** compete for the same numbers, and the second bind fails with the port already in use. The same is true of a container running in the host's own network view, which shares the machine's port space with everything else on it. This is one of the quiet wins of the model - workloads keep the port they were written for, instead of every team negotiating numbers on a shared machine.
go deeper
Recall that the port number lives inside the container's own network view, so many containers on one host can use the same number without any conflict.
Explain that binding claims a number within one port space, and name the two arrangements that reintroduce collisions: a shared network view, and running in the host's own view.
Diagnose an in-use bind failure precisely: identify which port space is contended and which listener already holds the number, rather than assuming a machine-wide conflict and restarting into the same wall.
Set the standard that a workload's port is part of its own contract and does not vary by environment, and treat the places where a shared port space returns as deliberate, documented coordination points.
## A port number is scoped, not global The instinct carried over from a single machine is that a port number belongs to the machine: if something is on 8080, nothing else can be. That was true because the machine had one network view and therefore one port space. A container normally has a private network view, and a port space comes with it. Binding a port is a claim inside **that** space. So `8080` in one container and `8080` in another are two different ports that happen to share a number, in the same way two houses can both have a room called 'the kitchen'. This has a practical consequence that is easy to under-rate: a workload keeps the port it was written for. No team has to renumber a service because another team got to 8080 first, no configuration has to be rewritten per environment, and the number in the code, the documentation and the health check all stay the same wherever the workload runs. ## Three cases, and what happens in each | Arrangement | Port space | Two listeners on 8080 | |---|---|---| | Two containers, each with its own view | one per container | both bind; no conflict | | Two containers sharing one network view | one, shared | the second bind fails - already in use | | A container running in the host's own view | the host's | conflicts with anything on the host using 8080 | The middle row is the one that surprises people, because the arrangement is chosen for a different reason entirely - usually so that one container can reach another over loopback. Sharing the view to get the loopback also means sharing the port space, and the port numbers have to be deconflicted by hand from that point on. ## What the collision looks like When it does happen, the failure is blunt and local: the process cannot start, and the error says the address is already in use. Three things are worth reading out of that: 1. **It is a bind failure, not a traffic failure.** Nothing was ever connected. The process died at start-up. 2. **It names a port space, not a machine.** The conflicting listener is inside the same view - a container sharing the view, or, for a container in the host's view, anything at all on the host. 3. **Retrying does not help.** Unless the other listener exits, the number stays claimed, so a restart loop just repeats the same failure. ## Why the model chooses scoping over a global registry The alternative designs are worse in obvious ways. A machine-wide registry that hands out ports would make every workload's port dynamic, which means nothing can be written into configuration ahead of time and every caller needs a lookup. Renumbering services per host makes an image behave differently depending on where it lands, which is the opposite of what an image is for. Scoping the number to the view gets both properties at once: - the port is **static and known** - part of the workload's own contract; - the port is **not a shared resource** between unrelated workloads on a host, so density does not require coordination. ## Where the collision moves to Scoping does not abolish contention, it relocates it. As soon as a port has to answer somewhere shared - on the host itself, or on an address other hosts can route to - that shared place has one port space again, and two workloads wanting the same number there do collide. Those hops are separate mechanisms with their own leaves; the point for this one is that the inside-the-view number and the outside-the-view number are different things and need not match. ## What is still unique per container One last precision, because it is a common muddle: containers with separate views also have separate addresses, so even if the platform wanted to route by port alone it would not have to - the address distinguishes them. The number is free precisely because the address is not. Two containers sharing one view are the mirror image: one address between them, so the number is the only thing left to tell their listeners apart, and it must therefore be unique.
- When does a port collision between two containers actually occur?When they share a port space. That means either two containers placed in one shared network view, or a container running in the host's own view competing with everything else on the machine. It also reappears wherever a port must answer at a shared place outside the view, which is a different mechanism with its own rules.
- If a bind fails with the address already in use inside a shared view, what are the options?Renumber one of the listeners, since the number is the only discriminator left once the two containers share one address. There is no way to have both on the same number in one view, and restarting simply repeats the failure until the other listener exits.
- Does a container's internal port number have to match the number anything outside uses?No. They are numbers in two different port spaces, and the mechanism that makes the workload answer somewhere else is free to use a different one. Keeping them the same is a convenience for humans, not a requirement of the model.
saying these in an interview costs you the question
- Believes a port number is unique per machine
- Says the platform silently remaps a duplicate port
- Thinks two containers sharing one view can both bind 8080
- Reads an in-use bind failure as a host-wide conflict
- Assumes the inside and outside port numbers must match