Docker Compose Network and Port Viewer

Work out who can reach whom. Publishing and exposing are about the host; what containers can reach each other on is decided entirely by which networks they share.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press View. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A flat stack

Both services share one network, and one port is bound to every interface

services:
  web:
    image: nginx
    ports:
      - "8080:80"
  db:
    image: postgres:16
    expose:
      - "5432"

Separated networks

The frontend genuinely cannot reach the database, and the database has no egress

services:
  web:
    image: nginx
    networks: [front]
  db:
    image: postgres:16
    networks: [back]
networks:
  front: {}
  back:
    internal: true

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Assuming a service is private because its port is not published

    Publishing is about the host. Every other container on the same network reaches it on any port it listens on.

    Instead:Put it on a separate network that only its consumers join.

  2. Using expose to restrict access

    It is documentation. It neither opens a port on the host nor limits what containers can reach.

    Instead:Use networks for isolation and ports for host access.

  3. Publishing a database port with no host address

    It binds every interface and reaches past the host firewall, so on a public host it is a database on the internet.

    Instead:Write "127.0.0.1:5432:5432".

Every service on the default network reaches every other, on any port

Compose puts them all on one network unless told otherwise, and there is no filtering on it. Publishing a port does not open it to other containers, and not publishing does not close it.

expose restricts nothing and publishes nothing

It is documentation inherited from the Dockerfile's EXPOSE. People assume it opens a port to the host, which it does not, and separately assume it limits what other containers can reach, which it also does not.

A published port with no host address binds every interface

And Docker's forwarding rules sit in front of the host firewall, so it answers from the network even under a default-deny policy. Writing "127.0.0.1:5432:5432" publishes to the loopback only, which is the correct form for anything behind a reverse proxy on the same host.

Separate networks are the actual control

A frontend network and a backend network, with the database only on the backend one, means the frontend genuinely cannot open a connection to the database. That is a property of the network layout rather than of the port configuration.

internal: true removes the outbound route

A container on an internal network alone cannot reach the internet at all. That is a real control for a database, and it also breaks anything expecting to fetch updates or call an external API, usually at the least convenient moment.

Service names resolve on every shared network

Docker's embedded DNS gives every service a name on each network it joins, which is why links is unnecessary and why two services on no common network cannot find each other at all.

What this cannot see

Whether the applications actually listen where they say. It reads the compose file, in your browser, and reaches nothing.