YAML Tools
Docker Compose Validator — Schema + Reference Checks
Syntax, schema and cross-reference errors in one report — catch a broken compose file before docker compose up does it for you.
In short
Validate a docker-compose.yml online against the Compose Specification schema, plus checks for undeclared volumes, networks and depends_on targets — every error with its line.
By NaveenKumar T · Updated
- Compose Specification JSON Schema (Ajv)
- Errors mapped to YAML line & column
- Undeclared volume / network / secret checks
Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →
Example
Docker Compose Validator: input and output
A three-service compose file with three deliberate mistakes: an obsolete version key, a typo'd enviroment key under web, and a named volume mounted by db that was never declared at the top level.
version: "3.8"
services:
web:
image: nginx:latest
ports:
- "8080:80"
enviroment:
- API_URL=https://api.example.com
depends_on:
- api
api:
image: myorg/api:1.0
networks:
- appnet
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
networks:
appnet: {}✗ Invalid — 1 schema error, 2 lint findings
Services 3 · Volumes 0 · Networks 1 · Schema compose-spec @ 2026-09-17
line 1, col 1 — version: obsolete under the Compose Specification — docker compose ignores it and prints a warning; remove it (version) [warning]
line 7, col 5 — services.web.enviroment: unknown key "enviroment": must NOT have unevaluated properties (unevaluatedProperties)
line 17, col 5 — services.db.volumes: service refers to undefined volume "pgdata" — declare it under the top-level volumes key (volumes)Three findings, each on its own reported line: the obsolete version key (a warning, not an error), enviroment rejected because it doesn't match any known service key and isn't an x- extension, and pgdata flagged as an undeclared volume because the file never adds a top-level volumes: section for it.
Learn more
Syntax, schema, semantics: the three ways a compose file breaks
A Docker Compose file can be broken at three completely different levels, and knowing which one you're looking at is most of the debugging work. SYNTAX errors are YAML problems — a tab where a space belongs, a missing colon, inconsistent indentation — and they stop the file from parsing at all. SCHEMA errors are Compose-specific: the YAML parses fine, but the document doesn't match the shape a Compose file is supposed to have — a typo'd key like enviroment, a value of the wrong type, a field that doesn't belong where it was placed. SEMANTIC errors are the subtlest: every individual value is shaped correctly, but the file is internally inconsistent — a service mounts a named volume that was never declared under the top-level volumes: key, or depends_on names a service that doesn't exist anywhere in the file.
This validator checks all three, in that order, in one pass: a YAML parse first (with the yaml package's own line/column-accurate error reporting), then the full document against the official Compose Specification's JSON Schema using Ajv's 2020-12 build (the schema itself declares draft 2020-12), then eight targeted cross-reference checks the schema's own vocabulary has no way to express — checks 3 through 5 below are exactly this kind of cross-reference problem, comparing one part of the document against another rather than checking one value in isolation.
Eight checks the schema cannot express
A JSON Schema validates one location in a document against a rule that only looks at that location — it has no native way to say "this value over here must match a key that exists somewhere else in the document." That's exactly the gap these eight checks close, run after schema validation whenever Scope is set to Schema + reference checks.
| # | Check | Severity | Why the schema can't express it |
|---|---|---|---|
| L1 | version: key is present | Warning | The schema accepts it for backward compatibility — its own description calls it ignored, but accepting isn't the same as flagging |
| L2 | depends_on names a service that isn't under services | Error | Cross-reference between two different parts of the document |
| L3 | A named volume mount isn't declared under top-level volumes | Error | Cross-reference; bind mounts (paths, ./ or ~) are correctly excluded |
| L4 | A service networks entry isn't declared under top-level networks | Error | Cross-reference (the implicit default network is exempt) |
| L5 | A secrets/configs reference isn't declared at the top level | Error | Cross-reference |
| L6 | The same host port is published by two services | Warning | Cross-SERVICE comparison — the schema validates one service at a time |
| L7 | container_name is set together with more than one replica | Error | A co-occurrence rule across two unrelated-looking fields |
| L8 | A service has neither image nor build | Error | A conditional requirement the schema's boolean logic doesn't encode here |
What this validator does not do, and what docker compose config does
Being honest about scope matters more than looking thorough: this page performs static analysis of the file exactly as written. It does not resolve ${VARIABLE} interpolation against your shell environment or a .env file, does not follow include: or extends: across other files, does not apply profiles:, does not check that an image reference actually exists in a registry, and does not check whether a host port is genuinely free on your machine. Those all require a live environment this validator deliberately doesn't have access to, since nothing you paste here ever leaves your browser.
docker compose config is the command that picks up exactly where this leaves off: it resolves every one of those, merges included files, and either prints the fully-resolved configuration or a specific error naming what's missing.
| Command | What it adds beyond this validator |
|---|---|
| docker compose config | Resolves ${VAR} interpolation, merges include/extends, applies profiles, prints the final config |
| docker compose config --quiet | Same resolution, but only exits non-zero on error — good for a CI gate |
Reading a finding
Every line in the report follows one format: line N, col M — path: message (keyword). The path is the dotted location inside the document (services.web.ports, for instance), and the keyword in parentheses is either an Ajv schema keyword (additionalProperties, required, type) or one of the eight semantic check codes from the table above, so you always know whether a finding came from the official schema or from this page's own cross-reference logic.
One more thing worth knowing before a report looks noisier than expected: the Compose Specification schema leans heavily on oneOf and anyOf for fields that accept several shapes (ports, volumes, depends_on, command — all of them can be written more than one way), and Ajv reports one full error per shape that a bad value failed to match. A single malformed ports entry can otherwise produce three or four nearly-identical lines. This validator groups those by location and keeps only the summary line plus the single most specific branch error, so one real mistake reads as one or two report lines instead of a wall of near-duplicates.
Help
Frequently asked questions
Everything you need to know about the Docker Compose Validator.
01How do I use this docker compose validator?
Paste or drop your compose.yml (or click Sample for a working three-service file) and press Validate. The report runs in three layers: YAML syntax first, then the file's shape against the official Compose Specification JSON Schema, then eight cross-reference checks the schema itself can't express — an undeclared volume, a depends_on target that doesn't exist, and similar mistakes. Every finding is reported as line N, col M so you can jump straight to it; the Scope switch turns the third layer off if you only want schema conformance.
02How is this different from the YAML Validator?
The same split this site already makes between /json-validator and /json-schema-validator, applied to Compose files: the YAML Validator checks only that a file is SYNTACTICALLY correct YAML — indentation, quoting, matched brackets — with no idea what a Compose file is supposed to contain. This page runs that same syntax check first, then adds two more layers: is the STRUCTURE a valid Compose file (the right keys, in the right shape, per the official Compose Specification schema), and do the CROSS-REFERENCES inside it hold together (does every volume, network, secret and depends_on target actually exist elsewhere in the file). A file can be perfect YAML and still be an invalid Compose file — enviroment: instead of environment: parses as fine YAML and fails here as an unknown key.
03Why does it warn about version: "3.8" when every tutorial has it?
Because the Compose Specification — the schema this validator runs against — merged the old 2.x/3.x file-format versions into one single, versionless spec, and the schema's own description for the version field says it plainly: "declared for backward compatibility, ignored. Please remove it." docker compose itself prints "the attribute `version` is obsolete" the moment it sees the key. It's harmless to leave in an existing file — nothing breaks — but a huge number of tutorials and older Stack Overflow answers still show it out of habit, which is exactly why this validator flags it as a warning rather than silently accepting it.
04Why does enviroment fail but x-logging pass?
The Compose Specification schema locks each service down to its known key set with additionalProperties/unevaluatedProperties: false, but deliberately carves out one exception — any key starting with x- is explicitly allowed everywhere via a patternProperties: { "^x-": {} } rule, because x- keys are the spec's official mechanism for vendor extensions and YAML anchors (x-common: &common is the standard trick for sharing config between services). enviroment isn't an x- key, so it hits the lockdown and fails as an unrecognized property; x-logging matches the extension pattern and sails through untouched, whatever it contains.
05Does it check that images exist, ports are free, or ${VARIABLES} resolve?
No — this is static analysis of the file as written, not a live check against Docker or your environment. It does not pull images to confirm they exist, check whether a host port is actually free, resolve ${VAR} interpolation against a .env file or your shell's environment, or follow include/extends across files. docker compose config is the tool that does all of that: it resolves interpolation, merges included files, applies profiles, and prints the fully-resolved configuration (or a clear error if something's missing) — run it locally once this validator confirms the file is structurally sound, for the checks that genuinely need a live environment to answer.
06Which Compose file version does it validate against?
The Compose Specification schema at the pinned commit named in the report's header line (Schema compose-spec @ <date>) — the same specification docker compose itself implements today, which subsumes the legacy docker-compose v1 2.x and 3.x file formats rather than treating them as separate targets. The Compose Specification is actively maintained; if a very recent field is missing here, it's worth checking whether the vendored schema has simply fallen behind the spec's latest revision.
Keep working
Related tools
YAML Validator
YAML Tools
JSON Schema Validator
Paste a document and a JSON Schema, press Validate, and get every violation at once — each one located by its JSON Pointer path and named by the keyword that failed. Runs Ajv entirely in your browser.
YAML Formatter
YAML Tools
YAML to JSON
Full YAML 1.2 parsing — anchors resolved, types preserved, errors pinpointed — straight into clean JSON.
YAML Viewer
YAML Tools
YAML Parser
YAML Tools