
Docker Errors Compose
- 9 installs
- 9 repo stars
- Updated July 8, 2026
- openaec-foundation/docker-claude-skill-package
Helps with devops & ci/cd tasks.
About
docker-errors-compose is a Claude Code skill for devops & ci/cd. It helps solo builders move faster with AI-assisted development.
- docker-errors-compose
- DevOps & CI/CD
- AI-coding skill
Docker Errors Compose by the numbers
- 9 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,020 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/docker-claude-skill-package --skill docker-errors-composeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 9 |
|---|---|
| repo stars | ★ 9 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/docker-claude-skill-package ↗ |
What it does
Helps with devops & ci/cd tasks.
Files
docker-errors-compose
Quick Reference
First Response: Validate the Compose File
ALWAYS run docker compose config before debugging any Compose error. This command parses, resolves variables, and renders the final configuration. If it fails, the Compose file itself is broken.
# Validate and render resolved config
docker compose config
# Validate without output (exit code only)
docker compose config -q
# Show resolved environment variables
docker compose config --environmentCritical Warnings
NEVER ignore docker compose config validation errors — they indicate structural problems that ALWAYS cause runtime failures.
NEVER use depends_on without condition: service_healthy when the dependent service needs initialization time (databases, message brokers). The default service_started condition only waits for the container to start, NOT for the application to be ready.
NEVER use the deprecated version: field — it is ignored by Compose v2 and generates warnings.
ALWAYS use named volumes for persistent data. Anonymous volumes are lost on docker compose down.
ALWAYS quote port mappings that start with numbers below 60 to prevent YAML parsing as sexagesimal (base-60) numbers.
---
Diagnostic Decision Tree
Compose File Won't Parse
docker compose config fails
├── YAML syntax error?
│ ├── Check indentation (spaces only, NEVER tabs)
│ ├── Check colons have space after them in mappings
│ └── Check strings with special chars are quoted
├── "services" missing?
│ └── The `services` key is REQUIRED — add it
├── Unknown attribute error?
│ ├── Check spelling of Compose directives
│ └── Check indentation level (attribute under wrong parent)
└── Variable interpolation error?
├── Unset variable? → Use ${VAR:-default} or set in .env
├── Dollar sign in value? → Escape with $$ (e.g., $$HOME)
└── Single-quoted in .env? → Values are literal, no interpolationServices Won't Start
docker compose up fails
├── Port conflict?
│ ├── "port is already allocated" → Find process: lsof -i :PORT
│ └── Two services using same host port → Change one
├── Dependency failure?
│ ├── "dependency failed to start" → Check dependent service logs
│ ├── Healthcheck timeout → Increase interval/retries/start_period
│ └── service_completed_successfully never exits 0 → Fix init service
├── Build failure?
│ ├── "build path ... does not exist" → Check context path
│ ├── Dockerfile not found → Check dockerfile path relative to context
│ └── Build context too large → Add .dockerignore
├── Image not found?
│ ├── "pull access denied" → docker login or check image name
│ └── "manifest unknown" → Verify tag exists in registry
├── Volume mount error?
│ ├── "permission denied" → Match UID/GID or fix ownership
│ ├── Named volume not declared → Add to top-level volumes:
│ └── External volume missing → Create it first
└── Environment variable error?
├── "variable is not set" → Define in .env or environment
└── Wrong value resolved → Check precedence orderOrphan Container Warnings
"Found orphan containers"
├── Service removed from compose.yaml → docker compose down --remove-orphans
├── Project name changed → Use consistent -p flag or COMPOSE_PROJECT_NAME
└── Suppress warning → Set COMPOSE_IGNORE_ORPHANS=true---
Error Diagnostic Table
| Error Message | Cause | Fix |
|---|---|---|
yaml: line N: did not find expected key | YAML indentation or syntax error | Check line N for tabs (use spaces), missing colons, or unquoted special characters |
services is required | Missing services: top-level key | Add services: as the top-level element |
service "X" refers to undefined network "Y" | Network used but not declared | Add network Y to top-level networks: section |
service "X" refers to undefined volume "Y" | Named volume used but not declared | Add volume Y to top-level volumes: section |
port is already allocated | Host port in use by another container or process | Find occupant: lsof -i :PORT or `ss -tlnp \ |
Bind for 0.0.0.0:PORT failed | Same as above — port conflict | Same fix as above |
dependency "X" is not a valid service | depends_on references nonexistent service | Check service name spelling in depends_on |
Found orphan containers | Services removed or project name changed | Run docker compose down --remove-orphans |
variable "X" is not set | Interpolation variable undefined | Define in .env file, or use ${X:-default} syntax |
invalid interpolation format | Malformed variable syntax | Check for unescaped $. Use $$ for literal dollar sign |
build path /path does not exist | Build context directory missing | Verify context: path exists relative to compose.yaml |
Cannot locate specified Dockerfile | Dockerfile path wrong | Check dockerfile: is relative to context:, not compose.yaml |
pull access denied for X | Image not found or authentication required | Run docker login. Verify image name and tag |
no matching manifest for linux/amd64 | Image not available for platform | Add platform: to service or use compatible image |
service "X" has neither an image nor a build context | Service needs image or build | Add image: or build: to the service definition |
"version" is obsolete | Deprecated version field | Remove the version: line entirely |
invalid service name "X" | Service name contains invalid characters | Use only [a-zA-Z0-9._-], start with letter or digit |
Compose file not found | No compose.yaml in directory | Create compose.yaml or use -f flag to specify path |
container name "X" is already in use | Stale container with same name exists | Run docker compose down first, or docker rm X |
network X declared as external but could not be found | External network does not exist | Create it: docker network create X |
volume X declared as external but not found | External volume does not exist | Create it: docker volume create X |
---
Common Patterns
Proper Service Dependencies with Healthcheck
services:
app:
image: myapp:latest
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3Safe Port Mapping
ports:
# ALWAYS quote port mappings to prevent YAML parsing issues
- "8080:80"
# Bind to localhost for development
- "127.0.0.1:5432:5432"Environment Variable with Required Check
environment:
DATABASE_URL: ${DATABASE_URL:?DATABASE_URL must be set}
LOG_LEVEL: ${LOG_LEVEL:-info}Validation Workflow
# Step 1: Validate syntax and variable resolution
docker compose config -q
# Step 2: Start with build and force recreation
docker compose up --build --force-recreate -d
# Step 3: Check service status
docker compose ps
# Step 4: Check logs for failing services
docker compose logs --tail 50 <service-name>---
Profile Dependency Resolution
When a profiled service depends on another profiled service, both profiles must be active or the dependency must have no profile:
services:
app:
image: myapp
debug-tools:
image: debug:latest
profiles: [debug]
depends_on:
- app # OK: app has no profile, always available
test-runner:
image: test:latest
profiles: [test]
depends_on:
- debug-tools # FAILS unless debug profile is also activeFix: Either activate both profiles (--profile test --profile debug), remove the cross-profile dependency, or remove the profile from the dependency.
---
Reference Links
- references/diagnostics.md -- Complete error message to cause to solution mapping
- references/examples.md -- Common Compose error scenarios with step-by-step fixes
- references/anti-patterns.md -- Compose configuration mistakes and corrections
Official Sources
- https://docs.docker.com/compose/compose-file/
- https://docs.docker.com/compose/compose-file/05-services/
- https://docs.docker.com/compose/how-tos/environment-variables/variable-interpolation/
- https://docs.docker.com/compose/how-tos/profiles/
- https://docs.docker.com/reference/cli/docker/compose/
Docker Compose Anti-Patterns
AP-01: Using depends_on Without Healthchecks
What happens: App starts before the database is ready, causing connection errors and crash loops.
# WRONG
services:
app:
depends_on:
- db
db:
image: postgres:16# CORRECT
services:
app:
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30sRule: ALWAYS use condition: service_healthy with a healthcheck for services that need initialization time (databases, message brokers, caches).
---
AP-02: Using the Deprecated version Field
What happens: Compose v2 ignores it and emits a warning. Developers waste time picking version numbers.
# WRONG
version: "3.8"
services:
web:
image: nginx# CORRECT
services:
web:
image: nginxRule: NEVER include version: in Compose files. The Compose Specification is the only format since Compose v2.
---
AP-03: Anonymous Volumes for Persistent Data
What happens: Data is lost when running docker compose down because anonymous volumes are not preserved.
# WRONG — anonymous volume
services:
db:
image: postgres:16
volumes:
- /var/lib/postgresql/data# CORRECT — named volume
services:
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Rule: ALWAYS use named volumes for any data that must survive container recreation.
---
AP-04: Hardcoding Secrets in Compose Files
What happens: Secrets committed to version control. Anyone with repo access sees credentials.
# WRONG
services:
db:
environment:
POSTGRES_PASSWORD: "super-secret-password"# CORRECT — interpolation from .env (add .env to .gitignore)
services:
db:
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}# BEST — use Docker secrets
services:
db:
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txtRule: NEVER hardcode passwords or API keys in Compose files. Use .env files (gitignored) or Docker secrets.
---
AP-05: Exposing Ports to All Interfaces
What happens: Services are accessible from any network interface, including public networks.
# WRONG — accessible from any interface
ports:
- "5432:5432"# CORRECT — bound to localhost only
ports:
- "127.0.0.1:5432:5432"Rule: ALWAYS bind development ports to 127.0.0.1 unless external access is explicitly required. Database ports (5432, 3306, 27017, 6379) should NEVER be exposed to all interfaces.
---
AP-06: Using container_name with Scalable Services
What happens: docker compose up --scale web=3 fails because container names must be unique.
# WRONG — prevents scaling
services:
web:
image: nginx
container_name: my-nginx# CORRECT — let Compose manage names
services:
web:
image: nginxRule: NEVER use container_name on services you might need to scale. Compose generates unique names automatically.
---
AP-07: Unquoted Port Mappings
What happens: YAML interprets numbers containing colons as sexagesimal (base-60) values. 56:56 becomes 3396.
# WRONG — potential YAML parsing surprise
ports:
- 56:56
- 80:80# CORRECT — always quote
ports:
- "56:56"
- "80:80"Rule: ALWAYS quote port mappings in Compose files to prevent YAML sexagesimal interpretation.
---
AP-08: restart: always Without Resource Limits
What happens: A crashing service restarts infinitely, consuming CPU and memory without bound.
# WRONG — crash loop with no limits
services:
app:
image: myapp
restart: always# CORRECT — restart with safety limits
services:
app:
image: myapp
restart: unless-stopped
deploy:
resources:
limits:
cpus: "0.50"
memory: 512MRule: ALWAYS combine restart: policies with resource limits via deploy.resources.limits to prevent runaway containers.
---
AP-09: Not Using Profiles for Optional Services
What happens: Debug tools, admin panels, and test utilities run in all environments, wasting resources and expanding the attack surface.
# WRONG — debug tools always running
services:
app:
image: myapp
phpmyadmin:
image: phpmyadmin
mailhog:
image: mailhog/mailhog# CORRECT — optional services behind profiles
services:
app:
image: myapp
phpmyadmin:
image: phpmyadmin
profiles: [debug]
mailhog:
image: mailhog/mailhog
profiles: [debug]# Start with debug tools only when needed
docker compose --profile debug up -dRule: ALWAYS assign profiles to services that are not needed in production (debug tools, admin panels, test services).
---
AP-10: Large Build Context Without .dockerignore
What happens: Docker sends the entire project directory (including node_modules, .git, data files) as build context. Builds are slow and may include sensitive files in the image.
# WRONG — no .dockerignore, sending everything
services:
app:
build: .Fix: Create .dockerignore in the build context:
node_modules
.git
.env
*.log
data/
dist/
coverage/Rule: ALWAYS create a .dockerignore file when using build: in Compose. At minimum, exclude .git/, node_modules/, and any data directories.
---
AP-11: Using Default Bridge Network
What happens: Services cannot resolve each other by name. DNS resolution only works on user-defined networks.
# WRONG — relying on default bridge (implicit)
services:
app:
image: myapp
network_mode: bridge
db:
image: postgres
network_mode: bridge# CORRECT — Compose creates a default user-defined network automatically
# Simply do not specify network_mode at all
services:
app:
image: myapp
db:
image: postgresRule: NEVER set network_mode: bridge explicitly. Compose automatically creates a user-defined bridge network with DNS resolution enabled.
---
AP-12: Missing Named Volume Declaration
What happens: docker compose config fails with "refers to undefined volume".
# WRONG — volume used but not declared
services:
db:
volumes:
- pgdata:/var/lib/postgresql/data# CORRECT — volume declared at top level
services:
db:
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Rule: ALWAYS declare named volumes in the top-level volumes: section. This is a Compose requirement, not optional.
---
AP-13: Ignoring docker compose config Output
What happens: Developers debug runtime issues that are caused by misconfigured Compose files. Hours spent on symptoms rather than root cause.
# WRONG workflow — jump straight to up and debug
docker compose up -d
docker compose logs
# ... head scratching ...# CORRECT workflow — validate first
docker compose config -q # Quick validation
docker compose config # Inspect resolved output
docker compose up -d # Start with confidenceRule: ALWAYS run docker compose config before docker compose up when troubleshooting. This catches YAML errors, undefined variables, missing volumes/networks, and merge issues before they become runtime failures.
---
AP-14: Cross-Profile Dependencies
What happens: Service A (profile: test) depends on Service B (profile: debug). Starting only the test profile leaves Service B inactive, causing dependency failure.
# WRONG — cross-profile dependency
services:
debug-db:
profiles: [debug]
test-runner:
profiles: [test]
depends_on:
- debug-db # Not started unless debug profile is active# CORRECT — shared profile or no profile on dependency
services:
debug-db:
profiles: [debug, test] # Available in both profiles
test-runner:
profiles: [test]
depends_on:
- debug-dbRule: NEVER create depends_on chains across different profiles unless you ALWAYS activate all required profiles together. Dependencies must share at least one profile with their dependents, or have no profile assignment.
Docker Compose Error Diagnostics — Complete Reference
YAML & File Parsing Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 1 | yaml: line N: did not find expected key | Indentation error, tab characters, or misplaced colon | Use spaces only (2-space indent standard). Check line N and surrounding lines for tabs or misaligned keys |
| 2 | yaml: line N: mapping values are not allowed here | Missing space after colon, or value on wrong line | Add space after colon: key: value not key:value. Check for unquoted strings containing colons |
| 3 | yaml: line N: could not find expected ':' | Missing colon in mapping, or incorrect list format | Ensure all mapping keys end with : . Check for missing - in list items |
| 4 | yaml: line N: found character that cannot start any token | Tab character in YAML | Replace all tabs with spaces. YAML forbids tabs for indentation |
| 5 | Compose file not found | No compose file in current directory | ALWAYS check you are in the correct directory. Create compose.yaml or specify with -f path/to/compose.yaml |
| 6 | services is required | Top-level services: key missing or empty | Add services: as a required top-level element with at least one service |
| 7 | Additional property X is not allowed | Misspelled or unsupported Compose directive | Check spelling against the Compose Specification. Verify indentation level is correct |
| 8 | "version" is obsolete | Deprecated version: field present | Remove the version: line. Compose v2 uses the unified Compose Specification and ignores this field |
Service Definition Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 9 | service "X" has neither an image nor a build context | Service missing both image: and build: | Add either image: <name> to pull an image or build: <path> to build from Dockerfile |
| 10 | invalid service name "X" | Service name contains invalid characters | Use only lowercase/uppercase letters, digits, hyphens, underscores, and dots. Must start with letter or digit |
| 11 | service "X" depends on undefined service "Y" | depends_on references a nonexistent service | Check spelling of service name in depends_on. Ensure the target service is defined in the same Compose file or an included file |
| 12 | container name "X" is already in use by container Y | A stopped or running container with the same container_name exists | Run docker rm X to remove the stale container, or run docker compose down first |
| 13 | service "X" refers to undefined network "Y" | Service uses a network not declared in top-level networks: | Add the network to the top-level networks: section, or fix the spelling |
| 14 | service "X" refers to undefined volume "Y" | Named volume used in service but not declared at top level | Add the volume to the top-level volumes: section |
| 15 | service "X" refers to undefined config "Y" | Config not declared in top-level configs: | Add the config to the top-level configs: section |
| 16 | service "X" refers to undefined secret "Y" | Secret not declared in top-level secrets: | Add the secret to the top-level secrets: section |
Port & Network Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 17 | port is already allocated | Another container or host process occupies the port | Find the process: lsof -i :PORT or `ss -tlnp \ |
| 18 | Bind for 0.0.0.0:PORT failed: port is already allocated | Same as above, explicit bind address | Same fix. Also check other Compose services for duplicate host port mappings |
| 19 | driver failed programming external connectivity on endpoint | iptables or firewall conflict | Restart Docker: sudo systemctl restart docker. Check firewall rules. Ensure net.ipv4.ip_forward=1 |
| 20 | network X declared as external, but could not be found | External network does not exist | Create it: docker network create X. Or remove external: true to let Compose manage it |
| 21 | Containers cannot reach each other by service name | Using default bridge network or misconfigured networks | Ensure services share a common user-defined network. NEVER rely on the default bridge for DNS resolution |
| 22 | network_mode and networks cannot be combined | Service has both network_mode: and networks: | Use one or the other. network_mode: host excludes custom networks |
Volume & Storage Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 23 | volume X declared as external, but could not be found | External volume does not exist | Create it: docker volume create X. Or remove external: true |
| 24 | Permission denied on mounted volume | UID/GID mismatch between host and container user | Match UIDs: set user: "1000:1000" in service. Or chown the host directory. Or adjust Dockerfile USER |
| 25 | Volume data lost after docker compose down | Using anonymous volume instead of named volume | ALWAYS declare named volumes in the top-level volumes: section and reference by name |
| 26 | Mounts denied: the path /host/path is not shared from the host | Docker Desktop file sharing restriction (macOS/Windows) | Add the path to Docker Desktop Settings > Resources > File Sharing |
| 27 | Volume mount overwrites container files | Bind mount or empty named volume replacing container directory | Use named volumes (they auto-populate from container). Or use docker cp to seed bind mounts |
Environment Variable Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 28 | variable "X" is not set | Variable used in interpolation but undefined | Define in .env file, shell environment, or use default: ${X:-default} |
| 29 | required variable "X" is missing a value | Variable with :? syntax is empty or unset | Set the variable. ${X:?message} errors when X is unset or empty |
| 30 | invalid interpolation format for X | Malformed ${} expression | Check for unclosed braces, nested interpolation (not supported), or stray $ signs |
| 31 | Wrong value resolved for variable | Precedence conflict between sources | Check precedence order: CLI -e > shell env > environment: > env_file: > Dockerfile ENV. Use docker compose config to verify |
| 32 | Literal ${VAR} appears in container | Value single-quoted in .env file | Single-quoted values are literal. Use double quotes or no quotes for interpolation |
| 33 | Dollar sign causes parse error | Unescaped $ in value | Escape with $$. Example: command: echo "$$HOME" |
Build Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 34 | build path /path does not exist | Build context directory not found | Verify context: path is relative to the Compose file directory. Check for typos |
| 35 | Cannot locate specified Dockerfile: Dockerfile | Dockerfile missing in build context | Check dockerfile: is relative to context:, NOT relative to compose.yaml. Default is Dockerfile in context root |
| 36 | failed to solve: dockerfile parse error | Syntax error in referenced Dockerfile | Check Dockerfile for typos, missing backslashes, wrong instruction names |
| 37 | COPY failed: file not found in build context | File outside context or excluded by .dockerignore | Verify file exists within the build context. Check .dockerignore patterns |
| 38 | error during connect: Get "https://...": dial tcp: lookup registry | Network issue during image pull in build | Check internet connectivity. Check DNS. Verify registry URL |
| 39 | Build context upload is extremely slow | Context directory contains large files (node_modules, .git, data) | Add a .dockerignore with large directories. ALWAYS ignore node_modules/, .git/, and build artifacts |
Dependency & Lifecycle Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 40 | dependency failed to start for service "X" | Dependent service crashed or failed healthcheck | Check dependent service logs: docker compose logs <dep>. Fix the underlying service error first |
| 41 | Service times out waiting for service_healthy | Healthcheck failing or intervals too short | Increase start_period, interval, and retries in healthcheck. Verify the health command works inside the container |
| 42 | service_completed_successfully never met | Init/migration service exits with non-zero code | Check service logs. Ensure the command exits with code 0 on success |
| 43 | Found orphan containers for this project | Services removed from Compose file but containers still exist | Run docker compose down --remove-orphans. Or set COMPOSE_IGNORE_ORPHANS=true to suppress |
| 44 | Service restarts in a loop | Application crash with restart: always | Check logs: docker compose logs <service>. Fix the application error. Use restart: on-failure:5 to limit retries |
Profile Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 45 | Profiled dependency not started | Service depends on a profiled service whose profile is not active | Activate required profile: --profile X. Or remove the profile from the dependency. Or remove the cross-profile dependency |
| 46 | docker compose up doesn't start profiled service | Profiles are opt-in, not default | Explicitly activate: --profile name or COMPOSE_PROFILES=name. Services with profiles are NEVER started by default |
| 47 | All services started when only profile wanted | Missing profile assignment on optional services | Add profiles: [name] to services that should be opt-in |
Compose Config Validation Errors
| # | Error Message | Cause | Fix |
|---|---|---|---|
| 48 | docker compose config shows unexpected values | Variable precedence or override file merging | Use docker compose config --environment to trace variable sources. Check for compose.override.yaml auto-loading |
| 49 | Merge conflict between Compose files | Duplicate resource definitions in included files | Rename conflicting resources. Use include: with paired override files for customization |
| 50 | no configuration file provided: not found | Neither compose.yaml nor docker-compose.yml exists | Create compose.yaml (preferred name). Or specify: docker compose -f custom.yaml up |
Diagnostic Commands Reference
| Command | Purpose |
|---|---|
docker compose config | Validate and render resolved Compose file |
docker compose config -q | Silent validation (exit code only) |
docker compose config --environment | Show resolved interpolation variables |
docker compose ps | List service container status |
docker compose ps -a | List all containers including stopped |
docker compose logs <service> | View service logs |
docker compose logs --tail 50 <service> | View last 50 log lines |
docker compose events | Stream real-time Compose events |
docker compose top | Display running processes per service |
docker compose port <service> <port> | Show public port mapping |
docker inspect <container> | Full container inspection |
docker compose down --remove-orphans | Clean stop with orphan removal |
docker compose up --force-recreate | Recreate all containers from scratch |
docker compose up --build | Rebuild images before starting |
Docker Compose Error Scenarios — Examples with Fixes
Scenario 1: Database Not Ready When App Starts
Symptom
Application crashes on startup with "connection refused" to database, even though depends_on is set.
Broken Configuration
services:
app:
image: myapp:latest
depends_on:
- db
environment:
DATABASE_URL: postgres://user:pass@db:5432/mydb
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: pass
POSTGRES_USER: user
POSTGRES_DB: mydbWhy It Fails
depends_on with default behavior (service_started) only waits for the container to start. PostgreSQL needs 5-15 seconds to initialize before accepting connections.
Fixed Configuration
services:
app:
image: myapp:latest
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://user:pass@db:5432/mydb
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: pass
POSTGRES_USER: user
POSTGRES_DB: mydb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s---
Scenario 2: Port Conflict Between Services
Symptom
Error response from daemon: driver failed programming external connectivity
on endpoint project-web-1: Bind for 0.0.0.0:8080 failed: port is already allocatedBroken Configuration
services:
web:
image: nginx
ports:
- "8080:80"
api:
image: myapi
ports:
- "8080:3000" # Duplicate host port!Fix
services:
web:
image: nginx
ports:
- "8080:80"
api:
image: myapi
ports:
- "8081:3000" # Different host portExternal Port Conflict Fix
If the port is used by a process outside Docker:
# Find what's using the port
lsof -i :8080
# or
ss -tlnp | grep 8080
# Stop the conflicting process, then retry
docker compose up -d---
Scenario 3: Environment Variable Not Set
Symptom
WARNING: The DATABASE_PASSWORD variable is not set. Defaulting to a blank string.Or with strict syntax:
variable "DATABASE_PASSWORD" is not set and is requiredBroken Configuration
services:
app:
image: myapp
environment:
DATABASE_PASSWORD: ${DATABASE_PASSWORD}Fix Option A: Create .env file
# Create .env in same directory as compose.yaml
echo "DATABASE_PASSWORD=my-secure-password" > .envFix Option B: Use default value
environment:
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-default-dev-password}Fix Option C: Require with error message
environment:
DATABASE_PASSWORD: ${DATABASE_PASSWORD:?DATABASE_PASSWORD must be set in .env or environment}Verify Resolution
docker compose config --environment---
Scenario 4: Orphan Container Warning
Symptom
WARN[0000] Found orphan containers ([project-old-service-1]) for this project.
Use 'docker compose down --remove-orphans' to clean them up.Cause
A service was removed from compose.yaml but its container still exists from a previous run.
Fix
# Remove orphan containers
docker compose down --remove-orphans
# Or suppress the warning permanently
export COMPOSE_IGNORE_ORPHANS=true---
Scenario 5: Volume Permission Denied
Symptom
Application log shows:
Error: EACCES: permission denied, open '/data/app.db'Broken Configuration
services:
app:
image: myapp # Runs as UID 1000
volumes:
- ./data:/data # Host dir owned by rootFix Option A: Match UID in Dockerfile
FROM node:20-alpine
RUN mkdir -p /data && chown -R node:node /data
USER nodeFix Option B: Set user in Compose
services:
app:
image: myapp
user: "${UID:-1000}:${GID:-1000}"
volumes:
- ./data:/dataFix Option C: Fix host directory ownership
sudo chown -R 1000:1000 ./data---
Scenario 6: Build Context Not Found
Symptom
failed to solve: failed to read dockerfile: open Dockerfile: no such file or directoryBroken Configuration
services:
app:
build:
context: ./backend
dockerfile: docker/Dockerfile # Relative to context!Project Structure
project/
compose.yaml
backend/
docker/
Dockerfile
src/Why It Fails
dockerfile path is relative to context, so Compose looks for ./backend/docker/Dockerfile. If the file is actually at ./docker/Dockerfile (relative to project root), it will not be found.
Fixed Configuration
services:
app:
build:
context: ./backend
dockerfile: docker/Dockerfile # Must exist at ./backend/docker/DockerfileOr if Dockerfile is at project root level:
services:
app:
build:
context: .
dockerfile: docker/Dockerfile # Now relative to project root---
Scenario 7: YAML Sexagesimal Port Parsing
Symptom
Port mapping produces unexpected numbers. Port 56:56 gets interpreted as 3396.
Broken Configuration
ports:
- 56:56 # YAML parses as sexagesimal (base-60): 5*60+6 = 306Fix
ports:
- "56:56" # ALWAYS quote port mappingsRule: ALWAYS quote port mappings in Compose files to prevent YAML base-60 interpretation.
---
Scenario 8: Dollar Sign in Environment Value
Symptom
invalid interpolation format for services.app.environment.PASSWORDBroken Configuration
services:
app:
environment:
PASSWORD: pa$$word # Compose tries to interpolate $$Fix
services:
app:
environment:
PASSWORD: "pa$$$$word" # $$ produces literal $Or use env_file with format: raw (Compose 2.30.0+):
services:
app:
env_file:
- path: ./secrets.env
format: raw # No interpolation---
Scenario 9: Profile Dependency Not Starting
Symptom
docker compose --profile test up
# test-runner starts but debug-tools does notBroken Configuration
services:
debug-tools:
image: debug:latest
profiles: [debug]
test-runner:
image: test:latest
profiles: [test]
depends_on:
- debug-tools # debug profile not active!Fix Option A: Activate both profiles
docker compose --profile test --profile debug upFix Option B: Remove profile from dependency
services:
debug-tools:
image: debug:latest
# No profile — always available
test-runner:
image: test:latest
profiles: [test]
depends_on:
- debug-toolsFix Option C: Share the same profile
services:
debug-tools:
image: debug:latest
profiles: [test, debug] # Active in both profiles
test-runner:
image: test:latest
profiles: [test]
depends_on:
- debug-tools---
Scenario 10: Named Volume Not Declared
Symptom
service "db" refers to undefined volume db-data: invalid compose projectBroken Configuration
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
# Missing top-level volumes declaration!Fix
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data: # ALWAYS declare named volumes at top level---
Scenario 11: External Network Does Not Exist
Symptom
network myshared declared as external, but could not be foundConfiguration
services:
app:
networks:
- myshared
networks:
myshared:
external: trueFix
# Create the external network first
docker network create myshared
# Then start Compose
docker compose up -d---
Scenario 12: Compose Override File Confusion
Symptom
Services have unexpected configuration. Port mappings or environment variables do not match what is in compose.yaml.
Cause
Compose automatically loads compose.override.yaml if it exists alongside compose.yaml. This is silent and can cause unexpected merging.
Diagnosis
# See the fully merged and resolved config
docker compose config
# Check which files are being loaded
docker compose config --resolve-image-digests 2>&1 | head -5Fix
Remove or rename compose.override.yaml if it is not intentional. Or explicitly control which files are loaded:
docker compose -f compose.yaml up -d # Only base file, no override