The 'invalid port specification' error occurs when Docker Compose cannot parse your port mapping syntax. This typically happens due to unquoted port values, undefined environment variables, or malformed port formats. Fix it by quoting ports as strings and validating your syntax.
The "Cannot create container for service: invalid port specification" error means Docker Compose failed to interpret your port mapping configuration in the `docker-compose.yml` file. Docker port mappings follow specific formats like `HOST:CONTAINER` (e.g., `8080:80`) or `IP:HOST:CONTAINER` (e.g., `127.0.0.1:8080:80`). When the configuration doesn't match these expected patterns, or when YAML parsing produces unexpected values, Docker rejects the specification. The most common culprit is YAML's base-60 number parsing. Without quotes, a port mapping like `80:25` is interpreted as a sexagesimal (base-60) number, resulting in `4825` instead of the intended host:container mapping. This is why Docker recommends always quoting port values as strings.
The most common fix is to wrap port mappings in quotes. YAML parses certain numeric patterns (like xx:yy where yy < 60) as base-60 numbers:
# WRONG: May be misinterpreted by YAML parser
services:
web:
ports:
- 8080:80
- 3000:3000
- 8025:25 # This becomes 4825 due to base-60 parsing!
# CORRECT: Always quote port mappings
services:
web:
ports:
- "8080:80"
- "3000:3000"
- "8025:25"This is the official Docker recommendation for avoiding YAML parsing surprises.
If the error shows invalid port specification: 'None', an environment variable is not being set:
# Check your docker-compose.yml
services:
web:
ports:
- "${WEB_PORT}:3000" # WEB_PORT might be undefinedSolutions:
1. Create a `.env` file in the same directory as docker-compose.yml:
# .env
WEB_PORT=80802. Provide a default value:
services:
web:
ports:
- "${WEB_PORT:-8080}:3000" # Uses 8080 if WEB_PORT is unset3. Export the variable before running docker-compose:
export WEB_PORT=8080
docker-compose upNote: env_file in docker-compose.yml only sets variables inside the container, not for the compose file parsing.
Ensure your port mappings follow valid formats:
# Valid short syntax formats
ports:
- "3000" # Container port only (Docker assigns host port)
- "3000-3005" # Container port range
- "8000:8000" # HOST:CONTAINER
- "9090-9091:8080-8081" # Port ranges (same count required)
- "127.0.0.1:8001:8001" # IP:HOST:CONTAINER
- "6060:6060/udp" # With protocol
- "127.0.0.1::3000" # IP::CONTAINER (random host port)
# INVALID formats
ports:
- "8080/udp:8080/udp" # Wrong! Protocol goes at the end
- "8080:8080:8080" # Wrong! Too many colons
- "8080:" # Wrong! Missing container port
- ":8080" # Wrong! Missing host portFor UDP ports, the protocol applies to the entire mapping:
ports:
- "12201:12201/udp" # Correct UDP syntaxThe long-form syntax is more explicit and avoids parsing issues:
services:
web:
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
dns:
ports:
- target: 53
published: 5353
protocol: udpLong-form fields:
- target: Container port (required)
- published: Host port (optional, Docker assigns if omitted)
- protocol: tcp or udp (default: tcp)
- host_ip: Host IP to bind (default: 0.0.0.0)
- mode: host or ingress (for Swarm)
This syntax eliminates YAML parsing ambiguity entirely.
If using port ranges, ensure they're valid:
# WRONG: Start port greater than end port
ports:
- "8082-8080:3002-3000"
# WRONG: Mismatched range sizes
ports:
- "8080-8082:3000-3001" # 3 ports to 2 ports
# CORRECT: Valid range with matching sizes
ports:
- "8080-8082:3000-3002" # 3 ports to 3 portsPort ranges must:
- Have start port <= end port
- Have the same number of ports on both sides of the colon
If ports come from Dockerfile ARG/ENV values, check for syntax errors:
# WRONG: Spaces around equals sign
ENV PORT = 3000
EXPOSE $PORT # Results in "Invalid containerPort: ="
# CORRECT: No spaces
ENV PORT=3000
EXPOSE $PORT
# Or use braces for clarity
ENV PORT=3000
EXPOSE ${PORT}Rebuild the image after fixing:
docker-compose build --no-cache
docker-compose upPort mappings are incompatible with network_mode: host:
# WRONG: Cannot use both
services:
web:
network_mode: host
ports:
- "8080:80" # Invalid with host network
# CORRECT: Host mode - no port mapping needed
services:
web:
network_mode: host
# Container uses host's network directly
# Access via whatever port the app listens on
# OR: Use bridge mode with port mapping
services:
web:
ports:
- "8080:80" # Works with default bridge networkWith host network mode, the container shares the host's network namespace directly, making port mapping unnecessary and invalid.
### Understanding YAML Base-60 Parsing
YAML interprets certain numeric patterns as sexagesimal (base-60) values, a legacy feature for time representation. The format xx:yy where yy < 60 is parsed as xx * 60 + yy:
# Without quotes, these are interpreted as numbers:
80:25 # = 80 * 60 + 25 = 4825
22:22 # = 22 * 60 + 22 = 1342
3:00 # = 3 * 60 + 0 = 180This is why "8025:25" works but 8025:25 may fail with strange port numbers.
### Version-Specific Issues
Several docker-compose versions had bugs with port parsing:
- v1.12.0: Broke ip::containerPort syntax
- v1.13.0: Introduced "None" errors when inheriting ports
- v1.14.0: Issues with UDP port syntax
If you suspect a version bug:
docker-compose version
# Consider upgrading or using a known stable version
pip install docker-compose==1.29.2 # Last v1 stable### Debugging Port Configuration
Validate your compose file before running:
# Check the parsed configuration
docker-compose config
# Look specifically at ports
docker-compose config | grep -A 5 "ports:"If the output shows unexpected values, you've found the parsing issue.
### Expose vs Ports
Don't confuse expose with ports:
services:
web:
expose:
- "3000" # Only accessible to linked services
ports:
- "8080:3000" # Accessible from hostexpose doesn't publish to the host - it just documents which ports the container listens on and makes them available to other containers on the same network.
### Port Specification in Docker Swarm
When deploying to Swarm, additional port modes apply:
services:
web:
ports:
- target: 80
published: 8080
mode: ingress # Load balanced across all nodes (default)
- target: 9090
published: 9090
mode: host # Only on the node running the taskInvalid mode values will cause port specification errors in Swarm deployments.
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub