API, Data & Developer Tools

Docker Compose Visualizer

Parse a Compose file safely and draw its services, networks, volumes, ports and depends_on graph, with common mistakes flagged and the diagram exportable as SVG.

  • Service graph
  • Port and volume tables
  • Findings
  • SVG export
Runs in your browser

Everything you paste, type or drop is processed in this browser tab. It is not uploaded, logged, stored or sent to analytics.

Compose visualizer workspace

1 Your Compose file

Try:

Drop compose.yaml here, or choose a file

.yaml or .yml up to 1 MB. Read in this tab only. Anchors and aliases are refused for safety - paste the output of docker compose config instead.

2 Diagram and findings

Paste a Compose file or load an example, then choose Visualise.

What the Docker Compose Visualizer does

This Docker Compose visualizer turns a compose.yaml into a diagram of its services, the depends_on arrows between them, and the ports, volumes and networks each one uses - and flags the mistakes that stop a stack from starting or quietly expose it. Everything happens in your browser; nothing is started, pulled or uploaded.

The file is read by a deliberately small, safe YAML reader that refuses anchors, aliases, merge keys and tags. That keeps a hostile file from expanding into millions of nodes, but it also means files that use x- blocks with &anchors must be expanded first with docker compose config.

How to use it

  1. Paste your compose.yaml, drop the file onto the box, or load one of the examples.
  2. Choose Visualise. The diagram places services that others depend on at the top and draws an arrow from each service to what it waits for.
  3. Read the findings, sorted with problems first. Services with findings get a coloured border in the diagram.
  4. Open the Services, ports and volumes tables for the details behind the drawing: dependency conditions, networks, host bindings and mount types.
  5. Download the diagram as a standalone SVG for documentation, or the findings as CSV for a ticket.

Reading the results

A solid arrow is a plain depends_on (start order only). A dashed arrow means the service waits for its dependency to be healthy or to complete successfully. A red arrow is part of a dependency cycle, which Compose refuses outright.

A problem is something Compose will reject or something with host-level consequences: an undeclared named volume, network or secret, an unknown or circular dependency, two services binding the same host port, privileged: true, or a mounted Docker socket. A warning is a common source of trouble - an unpinned image, a literal password in environment, or service_healthy pointing at a service with no healthcheck. A note is advice, such as binding a database port to 127.0.0.1.

Port clash detection follows the Compose short and long syntax, expands ranges such as 9000-9002, treats TCP and UDP separately, and understands that 127.0.0.1:8080 and 127.0.0.2:8080 can coexist while an all-interfaces binding overlaps both.

Worked example: the web shop example

The first example has five services: an nginx proxy, a web app built from ./web, a worker built from the same folder, PostgreSQL and Redis, on two declared networks with one declared volume, pgdata.

The tool reports 11 findings: 5 problems, 4 warnings and 2 notes. The problems: proxy and web both publish host port 80, so whichever starts second fails; the worker mounts /var/run/docker.sock, which is root on the host; Redis runs privileged; and Redis uses a named volume redis and a network metrics that are not declared at the top level, both of which make Compose refuse the file.

The warnings: nginx has no tag and postgres uses :latest; POSTGRES_PASSWORD is written into the file (whereas STRIPE_API_KEY: ${STRIPE_API_KEY} is correctly read from the environment and is not flagged); and web waits for db to be service_healthy although db defines no healthcheck. The notes: the obsolete version: line, and PostgreSQL published on all interfaces on port 5432.

The diagram has three rows - db and cache at the top, web and worker below them, and proxy at the bottom, because proxy depends on web.

Why anchors are refused

YAML anchors and aliases let one node be reused many times. Nested a few levels deep, a file of a few hundred bytes can expand to a billion nodes - the billion laughs attack - and freeze a browser tab. Tags such as !!python/object are the source of many deserialisation bugs. The reader used here supports neither, and rejects __proto__ and constructor as keys.

Compose files do use anchors legitimately for shared settings. docker compose config prints the fully merged, interpolated file with every anchor expanded; paste that output and the diagram shows exactly what Compose will run.

Limitations: what the result does not prove

  • Variables such as ${PORT} are shown as written and not substituted, so a port or image that comes from .env is not checked for clashes or tags.
  • It checks the structure of one file. Override files (compose.override.yaml), include:, extends: and profiles are not merged; run docker compose config with your real file set for that.
  • A clean result does not mean the stack will start: images, build contexts, host paths and external networks are not verified to exist.
  • Secret detection is by variable name and literal value, so a password under a neutral name is not caught.

Privacy: where your data goes

Everything you paste, type or drop is processed in this browser tab. It is not uploaded, logged, stored or sent to analytics. Session recording and tag-manager scripts are switched off on this page.

Standards and sources

Frequently asked questions

How do I see a diagram of my docker compose services?

Paste the compose.yaml here and choose Visualise. Each service becomes a box showing its image or build folder, published ports, mounts and networks, with arrows for depends_on. The SVG download is a standalone file you can put in a README or wiki.

Why does Compose say a named volume or network is undefined?

A named volume used by a service, such as pgdata:/var/lib/postgresql/data, must also be listed under the top-level volumes: key, and a named network under networks:. If you meant a folder on the host, start the path with ./ so it is read as a bind mount instead.

Does depends_on wait until my database is ready?

Only if you ask it to. Plain depends_on controls start order, not readiness. Use the long form with condition: service_healthy and give the database a healthcheck; without the healthcheck the condition can never be met and startup fails.

Can two Compose services publish the same host port?

Not on overlapping addresses. Only one process can bind port 80 on all interfaces, so the second container fails to start. Different specific addresses (127.0.0.1 and 127.0.0.2) can share a port number, and TCP and UDP bindings do not collide.

Is the version key still needed in a compose.yaml file?

No. The Compose Specification that current Docker Compose implements ignores the top-level version, and recent releases print a warning that it is obsolete. You can delete it; the file's features, not a version number, decide what is supported.

Why does this visualizer reject my file with anchors and aliases?

For safety: aliases can expand a tiny file into an enormous one (the billion laughs attack), so the YAML reader used here refuses them rather than risk freezing your tab. Run docker compose config locally and paste its output, which has every anchor already expanded.

Is my compose file uploaded anywhere?

No. The YAML is parsed and drawn in your browser, and no request carries its contents. That matters because Compose files often contain internal hostnames, registry paths and sometimes credentials.

Last reviewed by the A2Z.Tools team against the sources listed above.

Rate this tool

Was this tool useful? Your feedback helps us improve it.

No ratings yet — be the first to rate this tool.
Your rating (required)
0 / 2000

Please do not include passwords, payment details or other sensitive information.

Your feedback is sent privately to the A2Z.Tools team and will not be posted publicly.