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.

More docker tools

Docker Container Image Reference Parser Is that a registry or a Docker Hub user? Dockerfile Linter What this image will do to you later docker run to Kubernetes YAML And the flags that have no equivalent Docker Compose to Kubernetes And why depends_on has no equivalent Docker Logging Driver Generator json-file never rotates Dockerfile Non-Root USER Generator Numeric, or Kubernetes rejects it Docker OCI Image Labels Generator One of them actually does something Docker Hub Pull Rate Limit Calculator Counted per IP, not per person Docker Registry Storage Calculator Deleting a tag frees nothing Docker Build Context Analyzer All of it uploads before anything runs Docker Compose to docker run Converter Names stop resolving Docker Compose Version Migrator version: is obsolete now Docker Command Explainer Which flags hand over the host Docker BuildKit Cache Mount Generator apt deletes the cache you just mounted Docker BuildKit Secret Mount Generator ARG is in docker history forever Docker .dockerignore Pattern Tester *.log does not match logs/app.log Docker Image Manifest Viewer unknown/unknown is not broken Docker Image Config Viewer Anyone who can pull can read your Env Docker Registry Token Decoder Check the scope before the credentials Docker HEALTHCHECK Generator Docker does nothing when it fails Docker Network Subnet Calculator 31 networks, then it stops Docker History Analyzer The rm did not save anything Docker Run to Compose Converter Some flags have no equivalent Docker CMD and ENTRYPOINT Tester Why docker stop takes ten seconds Docker Port Mapping Tester -p reaches past your firewall Docker -v to --mount Converter -v invents missing directories Docker Restart Policy Simulator The backoff resets after ten seconds Docker Exit Code Explainer 137 is two different problems Docker CPU Limit Converter --cpu-shares limits nothing Docker Memory Limit Calculator -m 512m allows a gigabyte Docker Compose Interpolation Tester An unset variable is an empty string Docker Environment Variable Precedence Tester Your shell does not reach the container Docker Compose Override Merge Previewer An override can add a port, never remove one Dockerfile Multi-Stage Build Analyzer Which stages reach the image Dockerignore Validator It is not .gitignore

Elsewhere on the site