KhueApps
Home/DevOps/Diagnosing 'Service <name> failed to build' in Docker Compose

Diagnosing 'Service failed to build' in Docker Compose

Last updated: October 07, 2025

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

  1. 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>
      
  2. Expand and verify your Compose config:
    docker compose config
    
    Confirm the build.context, dockerfile path, args, and platform.
  3. Try building the Dockerfile directly (isolates Compose issues):
    docker build -f ./Dockerfile . --progress=plain --no-cache
    
  4. 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

  1. Confirm Compose and Docker versions

    • docker compose version
      docker version
      
    • Upgrade if severely outdated; new Compose features (platform, secrets, cache settings) require recent versions.
  2. 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
      
  3. 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.
  4. Reproduce outside Compose

    • docker build -f Dockerfile . --progress=plain
      
    • If this fails too, the issue is in Dockerfile or context, not Compose.
  5. 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: .
      
  6. 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.
  7. 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
      
  8. 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.
  9. 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.

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.

Series: Docker

DevOps