Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions content/manuals/engine/storage/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ of the writable layer of the container:
- [Volume mounts](#volume-mounts)
- [Bind mounts](#bind-mounts)
- [tmpfs mounts](#tmpfs-mounts)
- [Image mounts](#image-mounts)
- [Named pipes](#named-pipes)

No matter which type of mount you choose to use, the data looks the same from
Expand Down Expand Up @@ -85,6 +86,18 @@ such as caching intermediate data, handling sensitive information like
credentials, or reducing disk I/O. Use tmpfs mounts only when the data does not
need to persist beyond the current container session.

### Image mounts

An image mount makes the contents of another image available inside a container
at a path you choose. The mounted image is read-only and isn't part of the
container's own image, so you can bring in tools or assets from one image
without rebuilding another.

Use image mounts when you need to consume files packaged as an image, such as
mounting a tool-rich image to debug a minimal container, or sharing read-only
assets across containers running different images. Image mounts require the
[containerd image store](containerd.md).

### Named pipes

[Named pipes](https://docs.microsoft.com/en-us/windows/desktop/ipc/named-pipes)
Expand All @@ -99,6 +112,7 @@ Learn more about container data persistence:
- [Volumes](./volumes.md)
- [Bind mounts](./bind-mounts.md)
- [tmpfs mounts](./tmpfs.md)
- [Image mounts](./image-mounts.md)

Learn more about daemon storage backends:

Expand Down
5 changes: 3 additions & 2 deletions content/manuals/engine/storage/bind-mounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ $ docker run --mount type=bind,src=<host-path>,dst=<container-path>[,<key>=<valu

Valid options for `--mount type=bind` include:

| Option | Description |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Option | Description |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`, `src` | The location of the file or directory on the host. This can be an absolute or relative path. |
| `destination`, `dst`, `target` | The path where the file or directory is mounted in the container. Must be an absolute path. |
| `readonly`, `ro` | If present, causes the bind mount to be [mounted into the container as read-only](#use-a-read-only-bind-mount). |
Expand Down Expand Up @@ -486,4 +486,5 @@ and

- Learn about [volumes](./volumes.md).
- Learn about [tmpfs mounts](./tmpfs.md).
- Learn about [image mounts](./image-mounts.md).
- Learn about [storage drivers](/engine/storage/drivers/).
208 changes: 208 additions & 0 deletions content/manuals/engine/storage/image-mounts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
---
description: Using image mounts
title: Image mounts
weight: 40
keywords: storage, mounts, image mounts, image mount
---

[Volumes](volumes.md), [bind mounts](bind-mounts.md), and [tmpfs mounts](tmpfs.md)
all give a container a place to read and write data. An image mount is
different: instead of mounting a directory or a memory-backed filesystem, it
mounts the contents of another image into the container.

When you use an image mount, the filesystem of a second image is mounted into
the container at a path you choose. The container can read the files from that
image alongside its own filesystem, without those files being part of the
container's own image. This is useful when you want to bring the tools or assets
from one image into a container that's running a different image.

Image mounts are read-only. The mounted image is never modified, and the
container can't write to the mount.

> [!NOTE]
> Image mounts require the [containerd image store](containerd.md).

## When to use image mounts

Image mounts are appropriate for the following types of use case:

- Debugging a minimal or hardened image that doesn't include a shell or common
utilities. You can mount a tool-rich image, such as `busybox`, into the
running container's namespace and run those tools without changing the
original image. For a worked example, see
[Debug with Docker Hardened Images](/manuals/dhi/troubleshoot.md).

- Sharing read-only assets, such as datasets, models, or static content, that
are distributed as an image and consumed by containers running a different
image.

- Keeping application images small by packaging optional tooling in a separate
image and mounting it only when needed.

## Mounting over existing data

If you mount an image into a directory in the container in which files or
directories exist, the pre-existing files are obscured by the mount. This is
similar to if you were to save files into `/mnt` on a Linux host, and then
mounted a USB drive into `/mnt`. The contents of `/mnt` would be obscured by the
contents of the USB drive until the USB drive was unmounted.

With containers, there's no straightforward way of removing a mount to reveal
the obscured files again. Your best option is to recreate the container without
the mount.

## Considerations and constraints

- Image mounts are always read-only. The container can't modify the mounted
image, and changes aren't persisted anywhere.

- The source image must already exist in the daemon's image store. Docker
doesn't pull the source image automatically when you create the mount. If the
image isn't present, the command fails:

```console
$ docker run --mount type=image,source=busybox:musl,destination=/dbg alpine
docker: Error response from daemon: No such image: busybox:musl
```

Pull the image first with `docker pull`, then create the mount.

- Image mounts require the [containerd image store](containerd.md). They aren't
available when the daemon uses the classic storage drivers.

- You can only create an image mount with the `--mount` flag. There is no
`--volume` (`-v`) equivalent.

- Running an executable from a mounted image requires a compatible runtime in
the container. A dynamically linked binary only runs if the container provides
a matching dynamic linker and shared libraries. For example, a glibc-based
binary fails in a musl-based image such as Alpine. Statically linked binaries,
or mounting only data from an image, avoid this constraint.

## Syntax

To mount an image with the `docker run` command, use the `--mount` flag with
`type=image`.

```console
$ docker run --mount type=image,src=<image-reference>,dst=<container-path>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] docker run syntax examples are missing the required container image argument

Both syntax examples omit the container image positional argument that docker run requires:

$ docker run --mount type=image,src=<image-reference>,dst=<container-path>

Without an image name at the end, this command will fail. Since these are presented as runnable console examples (with a $ prompt), users will copy-paste and get an error. A corrected form would be:

$ docker run --mount type=image,src=<image-reference>,dst=<container-path> <container-image>

The same fix applies to the extended form on line 96.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That example is ambiguous though so maybe using something like:

$ docker run --mount type=image,src=<mounted-image>,dst=<container-path> <runtime-image>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion! Using <mounted-image> and <runtime-image> makes the distinction much clearer. The current <image-reference> and <container-path> labeling doesn't help users understand that there are two images involved: the one being mounted as a data source, and the one that's actually running as the container.

Your proposal removes that ambiguity nicely — it's immediately obvious which image is which.

```

The `--mount` flag consists of multiple key-value pairs, separated by commas and
each consisting of a `<key>=<value>` tuple. The order of the keys isn't
significant.

```console
$ docker run --mount type=image,src=<image-reference>,dst=<container-path>[,<key>=<value>...]
```

### Options for --mount

Valid options for `--mount type=image` include:

| Option | Description |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `source`, `src` | The reference of the image to mount, for example `busybox` or `busybox:musl`. The image must exist locally. |
| `destination`, `dst`, `target` | The path where the image is mounted in the container. Must be an absolute path. |
| `image-subpath` | Path inside the source image to mount instead of the image root. See [Mount a subpath of an image](#mount-a-subpath-of-an-image). |

```console {title="Example"}
$ docker run --mount type=image,src=busybox,dst=/dbg,image-subpath=bin
```

## Use an image mount in a container

The following example runs an Alpine container and mounts the `busybox:musl`
image at `/dbg`. Pull the source image first, since Docker doesn't pull it for
you when creating the mount. This example uses the musl-based BusyBox image so
its binaries are compatible with the musl-based Alpine container.

```console
$ docker pull busybox:musl
$ docker run -d \
-it \
--name imgtest \
--mount type=image,source=busybox:musl,destination=/dbg \
alpine:latest
```

The container can now read the BusyBox tools from `/dbg` while running the Alpine
image:

```console
$ docker exec imgtest /dbg/bin/echo "hello from busybox"
hello from busybox
```

Verify that the mount is an `image` mount by looking in the `Mounts` section of
the `docker inspect` output:

```console
$ docker inspect imgtest --format '{{ json .Mounts }}'
[{"Type":"image","Name":"busybox:musl","Source":"/var/lib/docker/rootfs/overlayfs/...","Destination":"/dbg","Mode":"","RW":false,"Propagation":"rprivate"}]
Comment thread
dvdksn marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] docker inspect example path prefix may not match containerd image store output

The example output shows:

"Source":"/var/lib/docker/rootfs/overlayfs/..."

Image mounts require the containerd image store. The actual source path on a containerd-backed daemon may differ from the /var/lib/docker/rootfs/overlayfs/ prefix shown. Users comparing this to their own docker inspect output could be confused if their path looks different.

Since the value is truncated with ..., it's clearly illustrative — but confirming the path prefix against a live containerd-image-store daemon (as mentioned in the PR description) and using the real prefix would make this more accurate.

```

This shows that the mount is an `image` mount, that its source is the
`busybox:musl` image, and that it's read-only (`"RW":false`).

Stop and remove the container:

```console
$ docker container rm -fv imgtest
```

## Mount a subpath of an image

Use the `image-subpath` option to mount a specific directory from the source
image instead of its root. For example, to mount only the `bin` directory of the
`busybox` image at `/tools`:

```console
$ docker run -d \
-it \
--name imgtest \
--mount type=image,source=busybox,destination=/tools,image-subpath=bin \
alpine:latest
```

The container sees the contents of the image's `bin` directory at `/tools`.

## Use an image mount with Docker Compose

A single Docker Compose service with an image mount looks like this:

```yaml
services:
app:
image: alpine:latest
volumes:
- type: image
source: busybox
target: /dbg
```

To mount a subpath of the image, use the `subpath` option under `image`:

```yaml
services:
app:
image: alpine:latest
volumes:
- type: image
source: busybox
target: /tools
image:
subpath: bin
```

The `image.subpath` option is available in Docker Compose version 2.35.0 and
later. For more information about using mounts of the `image` type with Compose,
see the
[Compose reference on the volume attribute](/reference/compose-file/services.md#volumes).

## Next steps

- Learn about [volumes](./volumes.md).
- Learn about [bind mounts](./bind-mounts.md).
- Learn about [tmpfs mounts](./tmpfs.md).
- Learn about [storage drivers](/engine/storage/drivers/).
1 change: 1 addition & 0 deletions content/manuals/engine/storage/tmpfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,5 @@ $ docker rm tmptest

- Learn about [volumes](volumes.md)
- Learn about [bind mounts](bind-mounts.md)
- Learn about [image mounts](image-mounts.md)
- Learn about [storage drivers](/engine/storage/drivers/)
1 change: 1 addition & 0 deletions content/manuals/engine/storage/volumes.md
Original file line number Diff line number Diff line change
Expand Up @@ -809,5 +809,6 @@ $ docker volume prune

- Learn about [bind mounts](bind-mounts.md).
- Learn about [tmpfs mounts](tmpfs.md).
- Learn about [image mounts](image-mounts.md).
- Learn about [storage drivers](/engine/storage/drivers/).
- Learn about [third-party volume driver plugins](/engine/extend/legacy_plugins/).