Terminus
Docker Compose Volume: Bind Mounts

Docker Compose Volume: Bind Mounts

The short answer

When working with Compose version 3, to mount a local directory into a Docker container (i.e. bind mount), you can use the [.inline-code]volumes[.inline-code] property in the [.inline-code]compose.yaml[.inline-code] file as follows:

 services:
  <service_name>:
    image: <image_name>
    volumes:
      - <host_directory>:<container_directory>:<access_mode>

Where:

  • [.inline-code]service_name[.inline-code] is the name of the service the volume will be mounted to.
  • [.inline-code]image_name[.inline-code] is the name of the Docker image the container will be launched from.
  • [.inline-code]host_directory[.inline-code] is the absolute or relative path of the bind mount on your local machine.
  • [.inline-code]container_directory[.inline-code] is the absolute path of the file or directory within the container.
  • [.inline-code]access_mode[.inline-code] is a comma separated list of options that determine the permissions of the bind mount.

For example:

 services:
  backend:
    image: ubuntu
    volumes:
      - ./app:/app:ro

The above command mounts the read-only [.inline-code]app[.inline-code] directory in the current directory into the container at the [.inline-code]/app[.inline-code] path.

Note that if the specified directory doesn't exist on your local machine, Docker will automatically create it before starting the container.

You can learn more about mounting files into a Docker container without Compose by reading our article on bind mounts.

[#recall-syntax-with-ai]Easily retrieve this syntax using Warp AI[#recall-syntax-with-ai]

If you’re using Warp as your terminal, you can easily retrieve this syntax using the Warp AI feature:

Entering [.inline-code]docker compose bind mount[.inline-code] in the AI question input will prompt a human-readable step by step guide including code snippets.

[#mounting-files]Mounting files and directories[#mounting-files]

To mount a file or a directory into a container, you can either use its relative or absolute path.

For example:

 # Mounts the `app` directory located in the root directory
volumes:
  - /app:/app
# Mounts the `app` directory located in the current directory
volumes:
  - ./app:/app
# Mounts the `app` directory located in the home directory
volumes:
  - ~/app:/app

Note that relative paths should always begin with [.inline-code].[.inline-code] or [.inline-code]..[.inline-code].

[#mounting-the-current-directory]Mounting the current directory[#mounting-the-current-directory]

To mount the current directory into the container at a specified path, you can use the dot syntax as follows:

 volumes:
  - .:/app

To mount the current directory at the same path into the container, you can use the command substitution syntax with the [.inline-code]pwd[.inline-code] command as follows:

 volumes:
  - "${PWD}:${PWD}"

Note that when using this syntax, Docker will automatically create all the intermediary directories starting from the root in order to preserve the directory structure.

[#using-multiple-bind-mounts] Using multiple bind mounts[#using-multiple-bind-mounts]

Compose allows you to mount multiple files and directories into a container by listing them one after the other as follows:

 volumes:
  - ./src:/app
  - ./cache:/tmp/cache
  - ./configs:/etc/configs

[#the-long-form-syntax]Using the long form syntax[#the-long-form-syntax]

Alternatively, Compose offers a different syntax called the long form syntax for creating bind mounts:

 volumes:
  - type: bind
    source: <host_path>
    target: <container_path>
    read_only: true

Note that, when creating bind mounts using the long syntax, the reference directory on the local host needs to be created beforehand as Docker won't automatically create it.

[#read-only-bind-mounts]Using read-only bind mounts[#read-only-bind-mounts]

By default, any modifications made by a container to the files and directories of a bind mount will be propagated back to the local machine (i.e. read-write mode).

To prevent that, you can define a bind mount as read-only, either using the [.inline-code]ro[.inline-code] option in the short form syntax:

 volumes:
  - ./app:/app:ro

Or the [.inline-code]read_only[.inline-code] property in the long form syntax:

 volumes:
  - type: bind
    source: ./app
    target: /app
    read_only: true