Overview
Seeing “Service <name> failed to build” during docker compose build or up means the image build for that service failed. The message is generic; the real cause is in the build output for the last failed step. This guide shows quick, repeatable steps to diagnose and fix it.
Quickstart: Fast Diagnosis
- Re-run with detailed logs and no cache:
- Linux/macOS:
DOCKER_BUILDKIT=1 docker compose build --no-cache --progress=plain <service> - Windows (PowerShell):
$env:DOCKER_BUILDKIT=1; docker compose build --no-cache --progress=plain <service>
- Linux/macOS:
- Expand and verify your Compose config:
Confirm the build.context, dockerfile path, args, and platform.docker compose config - Try building the Dockerfile directly (isolates Compose issues):
docker build -f ./Dockerfile . --progress=plain --no-cache - Fix the root cause reported at the failed step (often a RUN command, missing file, or network issue). Rebuild with cache after fixing.
Minimal Working Example (MWE)
Use this to verify your environment and Compose setup.
- File: compose.yaml
dervices: # Intentional typo will fail. Fix to: services
web:
build:
context: .
dockerfile: Dockerfile
container_name: demo-web
# Optional: enforce a specific platform (e.g., on Apple Silicon)
platform: linux/amd64
- File: Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
- File: app.py
print("Hello from Docker!")
- Optional: .dockerignore
.git
__pycache__
*.pyc
node_modules
Build and run:
# Fix the typo in compose.yaml to "services" first
sed -i.bak 's/dervices/services/' compose.yaml 2>/dev/null || true
docker compose build web
docker compose up web
Expected output: the container prints “Hello from Docker!” and exits.
If this MWE builds but your project does not, the problem is in your Dockerfile or Compose config for your project.
Step-by-Step Debugging
Confirm Compose and Docker versions
docker compose version docker version- Upgrade if severely outdated; new Compose features (platform, secrets, cache settings) require recent versions.
Verify build context and Dockerfile path
- In compose.yaml:
services: web: build: context: . dockerfile: Dockerfile - Check that context exists and Dockerfile path is correct. Run:
test -f Dockerfile && echo ok || echo missing
- In compose.yaml:
Re-run with plain logs and no cache
DOCKER_BUILDKIT=1 docker compose build --no-cache --progress=plain web- Scroll to the first “failed to solve” or “executor failed” line; fix that specific step.
Reproduce outside Compose
docker build -f Dockerfile . --progress=plain- If this fails too, the issue is in Dockerfile or context, not Compose.
Check platform/arch mismatches (e.g., Apple Silicon)
- Symptom: base image has no matching manifest.
- Fix: set a platform that exists in the base image:
services: web: platform: linux/amd64 build: context: .
Network and package manager issues
- Use noninteractive installs and always update indexes in the same layer:
RUN apt-get update && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* ENV DEBIAN_FRONTEND=noninteractive - Behind a proxy, pass build args and configure apt/npm as needed.
- Use noninteractive installs and always update indexes in the same layer:
File permissions and line endings
- Symptom: “exec format error” or “/bin/sh^M: bad interpreter”.
- Fix: convert to LF and set executable bits:
dos2unix script.sh && chmod +x script.sh git config core.autocrlf input
Missing files in image
- Symptom: COPY fails or app can’t find files.
- Fix: ensure paths are inside the build context and not excluded by .dockerignore.
Build args and secrets
- If your Dockerfile uses ARGs, define them:
services: api: build: context: . args: APP_ENV: production - Avoid putting credentials in ARG; prefer BuildKit secrets.
- If your Dockerfile uses ARGs, define them:
Common Symptoms, Causes, Fixes
Error: failed to read dockerfile: open Dockerfile: no such file
- Cause: wrong dockerfile path or context
- Fix: correct build.dockerfile or build.context
executor failed running [command]: exit code X
- Cause: command in RUN failed (missing deps, network issues)
- Fix: reproduce locally; add prerequisites; handle noninteractive installs
no matching manifest for platform
- Cause: base image doesn’t support your arch
- Fix: choose a multi-arch base or set service platform
permission denied when executing script
- Cause: missing +x or CRLF endings
- Fix: chmod +x and convert to LF
COPY failed: file not found in build context
- Cause: path outside context or ignored by .dockerignore
- Fix: move files under context or update .dockerignore
Pitfalls to Avoid
- Mixing image and build for the same service incorrectly; if both are present, Compose builds the image but may not tag/name as you expect. Prefer build with tags:
services: app: build: context: . image: myorg/app:dev - Sending huge contexts (node_modules, build outputs). Use .dockerignore.
- Multi-stage builds that reference a missing target. If you use target, ensure it exists.
- Relying on global environment variables unintentionally; pin values via build.args or env in Compose.
- Using old Compose v1 commands (docker-compose). Prefer docker compose (v2) for BuildKit features.
Performance Notes
- Enable BuildKit (faster, better caching):
export DOCKER_BUILDKIT=1 - Optimize cache layers:
- Order Dockerfile so rarely-changing lines (base, deps) come first.
- Separate dependency install from app COPY.
- Use .dockerignore to shrink contexts and speed builds.
- Multi-stage builds to keep images small and builds fast.
- Parallel builds for multiple services:
docker compose build --parallel - Cache export/import (buildx) for CI to speed rebuilds.
Tiny FAQ
Q: How do I see more verbose build logs?
- A: Use --progress=plain and DOCKER_BUILDKIT=1.
Q: Can I force a clean rebuild?
- A: Yes: docker compose build --no-cache <service>.
Q: Compose says the service failed, but what exactly failed?
- A: Check the last failed Dockerfile step; that message is the root cause.
Q: Why does COPY fail for files I can see locally?
- A: They might be outside the build context or ignored by .dockerignore.
Q: How do I handle Apple Silicon vs x86 base images?
- A: Use multi-arch images or set service-level platform: linux/amd64.
Q: Should I use image or build in Compose?
- A: Use build to build from Dockerfile; set image to tag the result.
Conclusion
“Service <name> failed to build” is a wrapper around a specific Dockerfile failure. Use plain logs, verify context and paths, fix the failing step, and apply best practices (.dockerignore, BuildKit, correct platforms) for reliable, fast builds.