services.web.ports must be a array — the ports key of the
web service holds a single string, and Compose's file check wants a list.
Put each mapping on its own line under ports:, starting with a dash, even
when there is only one.
The fix is one line break: ports: "127.0.0.1:15880:80" becomes
ports: followed by - "127.0.0.1:15880:80" on the next line,
indented under it. The message reads "a array", not "an array"; that is the wording this
Compose version printed, so search for it as it is.
The error
PS> docker compose up -d
validating C:\...\ports\compose.yaml: services.web.ports must be a array
The folder path in the first line was shortened. The command exited with code 1 and created nothing. The file that produced it:
name: fix8-d3-ports
services:
web:
image: alpine
command: ["sleep", "5"]
ports: "127.0.0.1:15880:80"
Why it happens
A service can publish several ports, so ports is a list in the Compose file
format, and a YAML list is written as lines that start with - (or as
["..."] on one line; ports: ["127.0.0.1:15880:80"] passed
docker compose config --quiet with exit code 0). A value after the colon on
the same line, without brackets, is a plain string. There was no YAML parse error; the
message starts with validating and names the path of the wrong key,
services.web.ports, and the type it expected.
The path in the message tells you where to look: the service name sits between
services. and the key. In a file with many services that is the fastest way
to find the line.
The fix
name: fix8-d3-ports
services:
web:
image: alpine
command: ["sleep", "5"]
ports:
- "127.0.0.1:15880:80"
PS> docker compose -f compose-fixed.yaml up -d
...
Container fix8-d3-ports-web-1 Started
PS> docker compose -f compose-fixed.yaml ps --format '{{.Name}} {{.Ports}}'
fix8-d3-ports-web-1 127.0.0.1:15880->80/tcp
With the dash the project started and docker compose ps showed the mapping
127.0.0.1:15880->80/tcp. The quotes around the mapping stayed as
they were; only its place in the file changed. The address in front,
127.0.0.1, is part of the mapping and was kept in the output of
docker compose ps.
How it was reproduced
One alpine service running sleep 5 with
ports: "127.0.0.1:15880:80" on a single line, started with
docker compose up -d from Windows PowerShell 5.1 on Docker Engine 29.9.2 and
Docker Compose v5.6.1 (Docker Desktop on Windows 11). The corrected file was saved as
compose-fixed.yaml beside it and started with -f. The
fix8-d3- names are this test's. The container and network were removed with
docker compose down.
Frequently asked
- What does 'services.web.ports must be a array' mean?
- The ports key of the web service holds a single string instead of a list. Compose's validating step rejects the file and starts nothing.
- How do I write ports in docker-compose.yml?
- Write ports: on its own line and each mapping below it on a line that starts with a dash, for example - "127.0.0.1:15880:80". Use the list form even for one mapping.
- Why does the Compose error say 'a array' instead of 'an array'?
- That is the wording Docker Compose v5.6.1 printed in this test. Search for the message exactly as printed; the fix is the same whatever the grammar.
More decoded errors in the Fixes category.