>DevOps Interview KB

What's the difference between a container's internal port and a host-published port, and how does confusing them cause debugging headaches?

BeginnerConceptualDocker5 min read

Short Answer

A container's internal port is whatever port the application inside the container actually listens on (e.g. an nginx process listening on port 80 inside its own network namespace) — this is fixed by the application's own configuration, not by Docker. The host-published port is a separate mapping Docker sets up on the host's network, forwarding traffic arriving at that host port to the container's internal port; in -p 8080:80, 8080 is the host port and 80 is the container's internal port, and the two numbers only need to match if you choose to make them match — they're independent by design.

Detailed Explanation

Every container has its own network namespace, meaning its own isolated view of network ports, completely independent from the host's port space — an application inside a container listening on port 80 is listening on port 80 within that container's namespace, which has no inherent connection to port 80 on the host, or on any other container. This is precisely why multiple containers can each run a web server on "port 80" simultaneously without conflict — each is port 80 in its own, separate network namespace.

Docker's -p <host-port>:<container-port> flag (or the equivalent in Docker Compose's ports: section) explicitly bridges these two separate port spaces: it tells Docker to listen on <host-port> on the host's actual network interface, and forward any traffic arriving there into the container, targeting <container-port> inside that container's namespace. The two numbers are genuinely independent — -p 8080:80 means "host port 8080 forwards to this container's internal port 80," and there's no requirement they match; -p 80:80 is just a common convention when it's convenient for the host port to match the container's internal port, not a technical necessity.

This distinction is a common source of confusion in a few concrete ways: connecting to localhost:80 when the actual publish mapping was -p 8080:80 fails, not because anything is broken, but because the host port genuinely is 8080, not 80 — the container's internal "80" was never directly reachable from the host at all, only through whatever host port was explicitly published to it. Similarly, a container trying to reach another container should generally use the target container's internal port directly (via Docker's DNS-based service discovery and the internal Docker network), not the host-published port — container-to-container traffic on the same Docker network doesn't go through the host's port-forwarding at all, it goes directly container-to-container within Docker's internal networking, making the host-published port entirely irrelevant to that specific traffic path.

Interview Follow-Up Questions

  • Why doesn't a container need a published host port at all if it's only ever accessed by other containers on the same Docker network?
  • How would you inspect a running container to confirm exactly what port mapping is actually configured, without guessing from the original `docker run` command?
  • What happens if you try to publish the same host port for two different containers simultaneously?

Key Takeaways

  • A container's internal port is fixed by whatever the application inside listens on, within that container's own isolated network namespace.
  • The host-published port is a separate, explicit mapping Docker sets up to forward host-arriving traffic into the container — the two numbers are independent unless deliberately matched.
  • Connecting to the wrong port number (host vs. container) from outside is a common, simple debugging trap once the distinction is understood.
  • Container-to-container traffic on the same Docker network uses the target's internal port directly, bypassing host-published port mapping entirely — a separate traffic path from external-to-host access.

References

Last updated August 21, 2026 · Last reviewed August 21, 2026