KhueApps
Home/DevOps/Fix 'working directory is invalid' in Docker Compose

Fix 'working directory is invalid' in Docker Compose

Last updated: October 07, 2025

Overview

The Compose error “working directory is invalid, it needs to be an absolute path” occurs when a service’s working_dir (or the Docker run -w flag it maps to) is set to a relative or incorrectly formatted path. The value must be an absolute path inside the container filesystem:

  • Linux containers: use POSIX paths such as /app
  • Windows containers: use Windows absolute paths such as C:\app

If you’re on macOS or Windows using Docker Desktop, you’re almost certainly running Linux containers unless you explicitly switched to Windows containers.

Quickstart: the fast fix

  1. Identify your container OS
  • Linux containers (most common): use /something
  • Windows containers: use C:\something
  1. Edit compose.yaml to set an absolute working_dir inside the container
  • Replace working_dir: . or working_dir: app with working_dir: /app (Linux) or working_dir: "C:\app" (Windows containers)
  1. Ensure volume mounts align with the working dir (optional but typical)
  • Map your project to the same path:
    • Linux: - ./:/app
    • Windows containers: - ./:C:\app
  1. Alternatively, define WORKDIR in the Dockerfile and remove working_dir from Compose to avoid inconsistencies.

  2. Re-run Compose

  • docker compose up --build

Minimal working example (Linux containers)

This example shows a correct absolute working_dir and a matching bind mount.

# compose.yaml
services:
  app:
    image: python:3.12-slim
    working_dir: /app
    volumes:
      - ./:/app
    command: python -c "import os; print(os.getcwd())"

Run:

docker compose up --quiet-pull

Expected output includes /app. No “working directory is invalid” error.

Minimal working example (Windows containers)

Only use this if you’ve explicitly switched Docker to Windows container mode.

# compose.yaml (Windows containers)
services:
  app:
    image: mcr.microsoft.com/windows/servercore:ltsc2022
    working_dir: "C:\\app"
    volumes:
      - ./:C:\\app
    command: cmd /S /C "cd && echo %CD%"

Preferred approach: set WORKDIR in Dockerfile

Defining WORKDIR in the image removes the need for working_dir in Compose and avoids path mismatches.

# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY . /app
CMD ["python", "-c", "import os; print(os.getcwd())"]

Then simplify compose.yaml:

services:
  app:
    build: .
    # working_dir not required because Dockerfile sets WORKDIR
    volumes:
      - ./:/app

Step-by-step diagnosis

  1. Check for relative values
  • Bad: working_dir: .
  • Bad: working_dir: app
  • Good: working_dir: /app (Linux) or "C:\app" (Windows containers)
  1. Validate environment variable expansion
  • Compose substitutes ${VAR} before sending to the engine.
  • If VAR is empty or yields a relative path, you’ll hit the error.
  • Example fix: working_dir: ${APP_DIR:-/app}
  1. Match container OS and path style
  • Linux containers: path must start with /
  • Windows containers: path must use a drive (e.g., C:\) and backslashes must be escaped in YAML strings.
  1. Avoid host paths for working_dir unless intended
  • working_dir is a container path, not a host path. Using ${PWD} is absolute but often undesirable; prefer a simple container path like /app.
  1. Confirm you didn’t accidentally override WORKDIR
  • If Dockerfile sets WORKDIR=/code and Compose sets working_dir: /app, your process runs in /app. Keep them consistent.
  1. Rebuild if you changed the Dockerfile
  • docker compose up --build ensures your changes apply.

Verification

  • Print the current directory from your command or entrypoint:
    • Linux: command: ["sh", "-lc", "pwd && ls -la"]
    • Windows containers: command: cmd /S /C "cd & dir"
  • Confirm the printed path matches your working_dir/WORKDIR.

Common pitfalls

  • Relative values (., ./app, app): always invalid.
  • Windows path used in Linux containers (C:\app): invalid. Use /app.
  • Linux path used in Windows containers (/app): invalid. Use C:\app.
  • Unset env var: working_dir: ${APP_DIR} expands to empty and fails.
  • YAML escaping on Windows containers: use quotes and escape backslashes ("C:\app").
  • Mismatch between WORKDIR and working_dir: can cause confusion and unexpected file locations.

Performance notes

  • working_dir itself has no meaningful performance impact. The heavy hitter is bind mounts.
  • On macOS/Windows with Linux containers, bind-mounting your entire repo can be slow. Options:
    • Mount only needed subdirs instead of the whole tree.
    • Use delegated/cached consistency flags where applicable:
      • Example: - ./:/app:delegated
    • For heavy I/O, prefer named volumes for dependency caches (e.g., pip cache, node_modules) to reduce host<->VM sync overhead.
  • COPY at build time is faster at runtime than bind mounting, but you’ll need rebuilds when files change. Use it for production images.

Tiny FAQ

Q: Does the directory need to exist in the image? A: No. Docker will create the working directory if it doesn’t exist.

Q: Can I use ${PWD} for working_dir? A: It may be absolute, but it couples container paths to your host. Prefer a stable container path like /app.

Q: Why does this work on Linux but fail on my Windows machine? A: You likely used Windows-style paths with Linux containers (or vice versa). Match the path style to the container OS, not the host OS.

Q: Should I set working_dir in Compose or WORKDIR in Dockerfile? A: Prefer WORKDIR in Dockerfile for portability. Use working_dir when you must override per service or environment.

Series: Docker

DevOps