Containers Intermediate

Resolving Docker Compose ‘Invalid Directory’ for Relative Path Volume Mounts on Ubuntu 22.04 LTS

Facing 'invalid directory' errors with Docker Compose relative volume mounts on Ubuntu 22.04? This guide diagnoses and fixes common path resolution issues, ensuring your containers persist data correctly.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Facing 'invalid directory' errors with Docker Compose relative volume mounts on Ubuntu 22.04? This guide diagnoses and fixes common path resolution issues, ensuring your containers persist data correctly.

Introduction

As an experienced Systems Administrator managing web hosting infrastructure, encountering issues with Docker Compose is a common occurrence. One of the more perplexing problems, particularly for those new to container orchestration or transitioning between environments, is the "invalid directory" error when using relative paths for volume mounts. On Ubuntu 22.04 LTS, this often manifests as a container failing to start, silently exiting, or explicitly throwing an error indicating that a specified host path does not exist. This guide will meticulously dissect the root causes behind this frustrating issue and provide a robust, step-by-step resolution process, ensuring your Dockerized applications correctly persist data.

Symptom & Error Signature

When attempting to bring up your Docker Compose services, typically using docker compose up -d, one or more containers might fail to start, producing an error message in the terminal or within the Docker daemon logs. The core issue indicates that Docker cannot locate or access the specified source directory on the host system.

A typical error signature observed on the command line might look like this:

[+] Running 1/2
 ⠿ Container myapp-db-1  Started
 ⠿ Container myapp-web-1  Error                                                                                                                                                                             0.1s
Error response from daemon: failed to create task for container myapp-web-1: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container: error creating bind mount target /var/lib/docker/volumes/<some_volume_id>/_data: stat /home/user/my_app/./data: no such file or directory: unknown

Alternatively, especially with slightly older Docker Compose versions or specific bind mount configurations, you might see:

ERROR: for web Cannot create container for service web: b'bind source path does not exist: /path/to/host/data'

In either case, the critical part of the message is the "no such file or directory" or "bind source path does not exist" referencing a path that you've specified as a host volume.

Root Cause Analysis

The "invalid directory" error for Docker Compose relative path volume mounts on Ubuntu 22.04 LTS primarily stems from a misunderstanding or misconfiguration of how Docker Compose resolves paths, combined with common filesystem issues.

  1. Incorrect Working Directory Context (The #1 Culprit): Docker Compose resolves relative paths in the volumes section of your docker-compose.yml file relative to the location of the docker-compose.yml file itself. It does not resolve them relative to your current shell's working directory (pwd) where you execute the docker compose up command, unless you explicitly specify the compose file path with -f. This is the most frequent cause of this error. For example, if your docker-compose.yml is in /home/user/my_app/ and contains volumes: - ./data:/app/data, but you run docker compose up from /home/user/, Docker Compose will look for /home/user/data instead of /home/user/my_app/data.

  2. Non-Existent Host Directory: The simplest explanation: the host directory specified in the volume mount simply does not exist. Docker Compose will not automatically create the host source directory for bind mounts. It will only create the target directory inside the container if it's missing, or the entire volume for named volumes.

  3. Typographical Errors: A minor typo in the relative path within docker-compose.yml or the actual directory name on the host filesystem can lead to this error.

  4. Insufficient Permissions: The Docker daemon, which typically runs as root (or through a rootless setup), or the user running docker compose might not have the necessary read and execute permissions to traverse the path segments leading to, or access, the specified host directory. While less common for "no such file or directory," it can present similar symptoms if a directory is inaccessible, making it appear non-existent.

  5. Symlink Resolution Issues: If any part of your relative path on the host system involves symbolic links, Docker's path resolution might differ from what you expect, especially if the symlink target itself is broken or inaccessible.

Step-by-Step Resolution

Addressing this issue requires a methodical approach, starting with verifying the basics and then diving into Docker Compose's specific context.

1. Verify Host Directory Existence and Path Accuracy

First, ensure that the intended host directory for your volume mount actually exists and that its path is spelled correctly.

  1. Identify the host path: Look at the volumes section in your docker-compose.yml. For example, if you have - ./my_data:/container_path, your host path is ./my_data relative to the docker-compose.yml file.
  2. Determine the absolute path: Navigate to the directory containing your docker-compose.yml file.
    cd /path/to/your/docker-compose.yml/directory
    
  3. Check for existence: Use ls -ld to confirm the directory exists.
    ls -ld ./my_data
    
    If ls -ld returns No such file or directory, then the problem is straightforward: the directory does not exist. You must create it:
    mkdir -p ./my_data
    

For bind mounts (host_path:container_path), the host_path must exist on the host filesystem before Docker Compose attempts to start the container. Docker Compose will only create named volumes or the target directory inside the container if it doesn't exist.

2. Understand Docker Compose's Working Directory Context

This is the most critical step for relative path issues. Docker Compose always resolves relative paths specified in volumes fields relative to the directory where the docker-compose.yml file itself is located.

Consider this docker-compose.yml located at /home/ubuntu/my_project/docker-compose.yml:

# /home/ubuntu/my_project/docker-compose.yml
version: '3.8'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html # This path will resolve to /home/ubuntu/my_project/html

Correct Execution Method:

Always navigate to the directory containing your docker-compose.yml before running docker compose up.

cd /home/ubuntu/my_project/
ls -ld html # Verify 'html' directory exists within this context
docker compose up -d

Incorrect Execution Example:

If you were in /home/ubuntu/ and tried to run:

# This is WRONG if 'docker-compose.yml' is in 'my_project/'
cd /home/ubuntu/
docker compose -f my_project/docker-compose.yml up -d

In this scenario, docker compose finds the YAML file, but the relative path ./html within the YAML file will be resolved relative to the YAML file's location (/home/ubuntu/my_project/), not /home/ubuntu/. This particular example would likely work, but it highlights the distinction. The common error happens when you run docker compose up from a directory without specifying -f, and the YAML file is in a subdirectory.

3. Use Absolute Paths for Clarity and Robustness (Recommended)

To eliminate any ambiguity related to working directory context, it's often best practice to use absolute paths for bind mounts. This makes your docker-compose.yml more robust against changes in execution context.

  1. Get the absolute path: While in the docker-compose.yml directory, use pwd to get the absolute path.

    cd /home/ubuntu/my_project/
    pwd # Output: /home/ubuntu/my_project
    
  2. Update docker-compose.yml: Modify your volumes entry to use the full absolute path.

    # /home/ubuntu/my_project/docker-compose.yml
    version: '3.8'
    services:
      web:
        image: nginx:latest
        ports:
          - "80:80"
        volumes:
          # Using absolute path:
          - /home/ubuntu/my_project/html:/usr/share/nginx/html
          # Or, if you want more flexibility, use environment variables:
          # - ${APP_DATA_DIR}/html:/usr/share/nginx/html
    

    If using environment variables, ensure APP_DATA_DIR is set in your shell before running docker compose up, or in a .env file co-located with docker-compose.yml.

    # .env file in /home/ubuntu/my_project/
    APP_DATA_DIR=/home/ubuntu/my_project
    

While absolute paths are highly robust, hardcoding user-specific paths like /home/ubuntu/ might reduce portability if your project is moved or deployed by different users/systems. Consider using environment variables (e.g., ${PROJECT_ROOT}/data) for better flexibility across environments.

4. Verify File System Permissions

Even if the directory exists, Docker might fail to access it due to incorrect permissions. The Docker daemon (running as root by default on Ubuntu 22.04) needs sufficient permissions to read from and write to the host directory.

  1. Check permissions: Use ls -ld on the specific directory and its parent directories up to the root to identify any access restrictions.

    ls -ld /home/ubuntu/my_project/html
    

    Look for read (r), write (w), and execute (x) permissions for the owner, group, and others. For Docker to traverse and use a directory, it typically needs at least read and execute permissions (r-x or 755) for the Docker daemon's effective user/group.

  2. Adjust permissions: If necessary, modify the permissions and ownership. For many web applications, matching the container's user ID (UID) and group ID (GID) with the host directory's ownership is ideal. A common web server user inside a container might be www-data with UID/GID 33.

    sudo chown -R 33:33 /home/ubuntu/my_project/html # Change ownership to www-data (UID 33)
    sudo chmod -R 755 /home/ubuntu/my_project/html # Grant read/execute to others, read/write/execute to owner/group
    

When adjusting permissions, always adhere to the principle of least privilege. Avoid overly permissive settings like chmod -R 777 as they can introduce significant security vulnerabilities, especially in production environments.

5. Address Symlinks (Advanced)

If your host path involves symbolic links, verify that the symlinks are correctly pointing to valid, accessible directories.

  1. Resolve symlinks: Use realpath to determine the ultimate target of any symlinks in your path.
    realpath /path/to/symlinked_data # e.g., realpath /home/ubuntu/my_project/html
    
    Ensure the path returned by realpath is the actual, existing directory and then apply the checks from steps 1 and 4 to that resolved path.

6. Clean Up and Re-run Docker Compose

Sometimes, Docker's internal state or cached information can lead to lingering issues. A clean shutdown and restart can resolve these.

  1. Stop and remove existing services:

    docker compose down
    
  2. Remove any lingering volumes (use with caution if you have named volumes with important data):

    docker compose down -v
    
  3. Perform a system-wide prune (use with extreme caution as this removes all stopped containers, networks, images, and build cache):

    docker system prune -a --volumes
    

    Confirm with y when prompted. Only use this if you are absolutely sure you want to clear all Docker-related resources not currently in use.

  4. Finally, try bringing up your services again from the correct directory:

    cd /path/to/your/docker-compose.yml/directory
    docker compose up -d
    

By meticulously following these steps, you should be able to diagnose and resolve the "invalid directory" error for Docker Compose relative path volume mounts on your Ubuntu 22.04 LTS system, ensuring your containers initialize and persist data correctly.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.