From a7d070ca2ccb285f1f8098449f18798bb10299a5 Mon Sep 17 00:00:00 2001 From: Misty Stanley-Jones Date: Wed, 9 Aug 2017 15:12:59 -0700 Subject: [PATCH] Improve data persistence documentation (#4018) --- _data/toc.yaml | 15 +- engine/admin/volumes/bind-mounts.md | 435 ++++++++++++++++++++++++++++ engine/admin/volumes/index.md | 175 +++++++++++ engine/admin/volumes/tmpfs.md | 144 +++++++++ engine/admin/volumes/volumes.md | 384 ++++++++++++++++++++++++ engine/tutorials/dockervolumes.md | 394 ------------------------- 6 files changed, 1151 insertions(+), 396 deletions(-) create mode 100644 engine/admin/volumes/bind-mounts.md create mode 100644 engine/admin/volumes/index.md create mode 100644 engine/admin/volumes/tmpfs.md create mode 100644 engine/admin/volumes/volumes.md delete mode 100644 engine/tutorials/dockervolumes.md diff --git a/_data/toc.yaml b/_data/toc.yaml index 7128a8834f..56b9389d30 100644 --- a/_data/toc.yaml +++ b/_data/toc.yaml @@ -164,8 +164,6 @@ guides: section: - path: /engine/tutorials/networkingcontainers/ title: Network containers - - path: /engine/tutorials/dockervolumes/ - title: Manage data in containers - path: /engine/docker-overview/ title: Docker overview - sectiontitle: User guide @@ -305,6 +303,19 @@ guides: title: Runtime metrics - path: /engine/admin/ambassador_pattern_linking/ title: Link via an ambassador container +- sectiontitle: Manage application data + section: + - path: /engine/admin/volumes/ + title: Storage overview + - path: /engine/admin/volumes/volumes/ + title: Volumes + - path: /engine/admin/volumes/bind-mounts/ + title: Bind mounts + - path: /engine/admin/volumes/tmpfs/ + title: tmpfs mounts + - path: /engine/userguide/storagedriver/ + title: Container storage drivers + nosync: true - sectiontitle: Troubleshoot Docker Engine section: - path: /engine/admin/troubleshooting_volume_errors/ diff --git a/engine/admin/volumes/bind-mounts.md b/engine/admin/volumes/bind-mounts.md new file mode 100644 index 0000000000..5262fb4fb3 --- /dev/null +++ b/engine/admin/volumes/bind-mounts.md @@ -0,0 +1,435 @@ +--- +description: Using bind mounts +title: Use bind mounts +keywords: storage, persistence, data persistence, mounts, bind mounts +--- + +Bind mounts have been around since the early days of Docker. Bind mounts have +limited functionality compared to [volumes](volumes.md). When you use a bind +mount, a file or directory on the _host machine_ is mounted into a container. +The file or directory is referenced by its full or relative path on the host +machine. By contrast, when you use a volume, a new directory is created within +Docker's storage directory on the host machine, and Docker manages that +directory's contents. + +The file or directory does not need to exist on the Docker host already. It is +created on demand if it does not yet exist. Bind mounts are very performant, but +they rely on the host machine's filesystem having a specific directory structure +available. If you are developing new Docker applications, consider using [named +volumes](volumes.md) instead. You can't use Docker CLI commands to directly +manage bind mounts. + +## Choosing the -v or --mount flag + +Originally, the `-v` or `--volume` flag was used for standalone containers and +the `--mount` flag was used for swarm services. However, starting with Docker +17.06, you can also use `--mount` with standalone containers. In general, +`--mount` is more explicit and verbose. The biggest difference is that the `-v` +syntax combines all the options together in one field, while the `--mount` +syntax separates them. Here is a comparison of the syntax for each flag. + +> **Tip**: New users should use the `--mount` syntax. Experienced users may +> be more familiar with the `-v` or `--volume` syntax, but are encouraged to +> use `--mount`, because research has shown it to be easier to use. + +- **`-v` or `--volume`**: Consists of three fields, separated by colon characters + (`:`). The fields must be in the correct order, and the meaning of each field + is not immediately obvious. + - In the case of bind mounts, the first field is the path to the file or + directory on the **host machine**. + - The second field is the path where the file or directory will be mounted in + the container. + - The third field is optional, and is a comma-separated list of options, such + as `ro`, `consistent`, `delegated`, `cached`, `z`, and `Z`. These options + are discussed below. + +- **`--mount`**: Consists of multiple key-value pairs, separated by commas and each + consisting of a `=` tuple. The `--mount` syntax is more verbose + than `-v` or `--volume`, but the order of the keys is not significant, and + the value of the flag is easier to understand. + - The `type` of the mount, which can be `bind`, `volume`, or `tmpfs`. This + topic discusses bind mounts, so the type will always be `bind`. + - The `source` of the mount. For bind mounts, this is the path to the file + or directory on the Docker daemon host. May be specified as `source` or + `src`. + - The `destination` takes as its value the path where the file or directory + will be mounted in the container. May be specified as `destination`, `dst`, + or `target`. + - The `readonly` option, if present, causes the bind mount to be [mounted into + the container as read-only](#use-a-read-only-bind-mount). + - The `bind-propagation` option, if present, changes the + [bind propagation](#configure-bind-propagation). May be one of `rprivate`, + `private`, `rshared`, `shared`, `rslave`, `slave`. + - The [`consistency`](#configure-mount-consistency-for-macos) option, if + present, may be one of `consistent`, `delegated`, or `cached`. This setting + only applies to Docker for Mac, and is ignored on all other platforms. + - The `--mount` flag does not support `z` or `Z` options for modifying + selinux labels. + +The examples below show both the `--mount` and `-v` syntax where possible, and +`--mount` is presented first. + +### Differences between `-v` and `--mount` behavior + +Because the `-v` and `--volume` flags have been a part of Docker for a long +time, their behavior cannot be changed. This means that **there is one behavior +that is different between `-v` and `--mount`.** + +If you use `-v` or `--volume` to bind-mount a file or directory that does not +yet exist on the Docker host, `-v` will create the endpoint for you. **It is +always created as a directory.** + +If you use `--mount` to bind-mount a file or directory that does not +yet exist on the Docker host, Docker does **not** automatically create it for +you, but generates an error. + +## Start a container with a bind mount + +Consider a case where you have a directory `source` and that when you build the +source code, the artifacts are saved into another directory `source/target/`. +You want the artifacts to be available to the container at `/app/`, and you +want the container to get access to a new build each time you build the source +on your development host. Use the following command to bind-mount the `target/` +directory into your container at `/app/`. Run the command from within the +`source` directory. The `$(pwd)` sub-command expands to the current working +directory on Linux or macOS hosts. + +The `--mount` and `-v` examples below produce the same result. You +can't run them both unless you remove the `devtest` container after running the +first one. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + --mount source=$(pwd)/target,target=/app \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + -v $(pwd)/target:/app \ + nginx:latest +``` + +
+
+ +Use `docker inspect devtest` to verify that the bind mount was created +correctly. Look for the `Mounts` section: + +```json +"Mounts": [ + { + "Type": "bind", + "Source": "/tmp/source/target", + "Destination": "/app", + "Mode": "", + "RW": true, + "Propagation": "rprivate" + } +], +``` + +This shows that the mount is a `bind` mount, it shows the correct source and +destination, it shows that the mount is read-write, and that the propagation is +set to `rprivate`. + +Stop the container: + +```bash +$ docker container stop devtest + +$ docker container rm devtest +``` + +### Mounting into a non-empty directory on the container + +If you bind-mount into a non-empty directory on the container, the directory's +existing contents will be obscured by the bind mount. This can be beneficial, +such as when you want to test a new version of your application without +building a new image. However, it can also be surprising and this behavior +differs from that of [docker volumes](volumes.md). + +This example is contrived to be extreme, but will replace the contents of the +container's `/usr/` directory with the `/tmp/` directory on the host machine. In +most cases, this would result in a non-functioning container. + +The `--mount` and `-v` examples have the same end result. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name broken-container \ + --mount source=/tmp,target=/usr \ + nginx:latest + +docker: Error response from daemon: oci runtime error: container_linux.go:262: +starting container process caused "exec: \"nginx\": executable file not found in $PATH". +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name broken-container \ + -v /tmp:/usr \ + nginx:latest + +docker: Error response from daemon: oci runtime error: container_linux.go:262: +starting container process caused "exec: \"nginx\": executable file not found in $PATH". +``` + +
+
+ +The container is created but does not start. Remove it: + +```bash +$ docker container rm broken-container +``` + +## Use a read-only bind mount + +For some development applications, it is useful for the container to be able to +write into the bind mount, in order for changes to be propagated back to the +Docker host. At other times, the container should only be able to read the +data and not modify it. + +This example modifies the one above but mounts the directory as a read-only +bind mount, by adding `ro` to the (empty by default) list of options, after the +mount point within the container. Where multiple options are present, separate +them by commas. + +The `--mount` and `-v` examples have the same result. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + --mount source=$(pwd)/target,target=/app,readonly \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + -v $(pwd)/target:/app:ro \ + nginx:latest +``` + +
+
+ +Use `docker inspect devtest` to verify that the bind mount was created +correctly. Look for the `Mounts` section: + +```json +"Mounts": [ + { + "Type": "bind", + "Source": "/tmp/source/target", + "Destination": "/app", + "Mode": "ro", + "RW": false, + "Propagation": "rprivate" + } +], +``` + +Stop the container: + +```bash +$ docker container stop devtest + +$ docker container rm devtest +``` + +## Configure bind propagation + +Bind propagation defaults to `rprivate` for both bind mounts and volumes. It is +only configurable for bind mounts, and only on Linux host machines. Bind +propagation is an advanced topic and many users never need to configure it. + +Bind propagation refers to whether or not mounts created within a given +bind-mount or named volume can be propagated to replicas of that mount. Consider +a mount point `/mnt`, which is also mounted on `/tmp`. The propagation settings +control whether a mount on `/tmp/a` would also be available on `/mnt/a`. Each +propagation setting has a recursive counterpoint. In the case of recursion, +consider that `/tmp/a` is also mounted as `/foo`. The propagation settings +control whether `/mnt/a` and/or `/tmp/a` would exist. + +| Propagation setting | Description | +|:--------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `shared` | Sub-mounts of the original mount are exposed to replica mounts, and sub-mounts of replica mounts are also propagated to the original mount. | +| `slave` | similar to a shared mount, but only in one direction. If the original mount exposes a sub-mount, the replica mount can see it. However, if the replica mount exposes a sub-mount, the original mount cannot see it. | +| `private` | The mount is private. Sub-mounts within it are not exposed to replica mounts, and sub-mounts of replica mounts are not exposed to the original mount. | +| `rshared` | The same as shared, but the propagation also extends to and from mount points nested within any of the original or replica mount points. | +| `rslave` | The same as slave, but the propagation also extends to and from mount points nested within any of the original or replica mount points. | +| `rprivate` | The default. The same as private, meaning that no mount points anywhere within the original or replica mount points propagate in either direction. | + +Before you can set bind propagation on a mount point, the host filesystem needs +to already support bind propagation. + +For more information about bind propagation, see the +[Linux kernel documentation for shared subtree](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt){: target="_blank" class="_"}. + +The following example mounts the `target/` directory into the container twice, +and the second mount sets both the `ro` option and the `rslave` bind propagation +option. + +The `--mount` and `-v` examples have the same result. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + --mount source=$(pwd)/target,target=/app \ + --mount source=$(pwd)/target,target=/app2,readonly,bind-propagation=rslave \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + -v $(pwd)/target:/app \ + -v $(pwd)/target:/app2:ro,rslave \ + nginx:latest +``` + +
+
+ +Now if you create `/app/foo/`, `/app2/foo/` will also exist. + +## Configure the selinux label + +If you use `selinux` you can add the `z` or `Z` options to modify the selinux +label of the **host file or directory** being mounted into the container. This +affects the file or directory on the host machine itself and can have +consequences outside of the scope of Docker. + +- The `z` option indicates that the bind mount content is shared among multiple + containers. +- The `Z` option indicates that the bind mount content is private and unshared. + +Use **extreme** caution with these options. Bind-mounting a system directory +such as `/home` or `/usr` with the `Z` option will render your host machine +inoperable and you may need to relabel the host machine files by hand. + +This example sets the `z` option to specify that multiple containers can share +the bind mount's contents: + +It is not possible to modify the selinux label using the `--mount` flag. + +```bash +$ docker run -d \ + -it \ + --name devtest \ + -v $(pwd)/target:/app:z \ + nginx:latest +``` + +## Configure mount consistency for macOS + +Docker for Mac uses `osxfs` to propagate directories and files shared from macOS +to the Linux VM. This propagation makes these directories and files available to +Docker containers running on Docker for Mac. + +By default, these shares are fully-consistent, meaning that every time a write +happens on the macOS host or through a mount in a container, the changes are +flushed to disk so that all participants in the share have a fully-consistent +view. Full consistency can severely impact performance in some cases. Docker +17.05 and higher introduce options to tune the consistency setting on a +per-mount, per-container basis. The following options are available: + +- `consistent` or `default`: The default setting with full consistency, as + described above. + +- `delegated`: The container runtime's view of the mount is authoritative. There + may be delays before updates made in a container are visible on the host. + +- `cached`: The macOS host's view of the mount is authoritative. There may be + delays before updates made on the host are visible within a container. + +These options are completely ignored on all host operating systems except macOS. + +The `--mount` and `-v` examples have the same result. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + --mount source=$(pwd)/target,destination=/app,consistency=cached \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + -v $(pwd)/target:/app:cached \ + nginx:latest +``` + +
+
+ +## Next steps + +- Learn about [volumes](volumes.md). +- Learn about [tmpfs mounts](tmpfs.md). +- Learn about [storage drivers](/engine/userguide/storagedriver.md). \ No newline at end of file diff --git a/engine/admin/volumes/index.md b/engine/admin/volumes/index.md new file mode 100644 index 0000000000..88c013de80 --- /dev/null +++ b/engine/admin/volumes/index.md @@ -0,0 +1,175 @@ +--- +description: Overview of persisting data in containers +title: Manage data in Docker +keywords: storage, persistence, data persistence, volumes, mounts, bind mounts +--- + +It is possible to store data within the writable layer of a container, but there +are some downsides: + +- The data won't persist when that container is no longer running, and it can be + difficult to get the data out of the container if another process needs it. +- A container's writable layer is tightly coupled to the host machine + where the container is running. You can't easily move the data somewhere else. +- Writing into a container's writable layer requires a + [storage driver](/engine/userguide/storagedriver.md) to manage the + filesystem. The storage driver provides a union filesystem, using the Linux + kernel. This extra abstraction reduces performance as compared to using + _data volumes_, which write directly to the host filesystem. + +Docker offers three different ways to mount data into a container from the +Docker host: _volumes_, _bind mounts_, or _`tmpfs` volumes_. When in doubt, +volumes are almost always the right choice. Keep reading for more information +about each mechanism for mounting data into containers. + +## Choose the right type of mount + +No matter which type of mount you choose to use, the data looks the same from +within the container. It is exposed as either a directory or an individual file +in the container's filesystem. + +An easy way to visualize the difference among volumes, bind mounts, and `tmpfs` +mounts is to think about where the data lives on the Docker host: + +- **Volumes** are stored in a part of the host filesystem which is _managed by + Docker_ (`/var/lib/docker/volumes/` on Linux). Non-Docker processes should not + modify this part of the filesystem. Volumes are the best way to persist data + in Docker. + +- **Bind mounts** may be stored *anywhere* on the host system. They may even be + important system files or directories. Non-Docker processes on the Docker host + or a Docker container can modify them at any time. + +- **`tmpfs` mounts** are stored in the host system's memory only, and are never + written to the host system's filesystem. + +### More details about mount types + +- **[Volumes](volumes.md)**: Created and managed by Docker. You can create a + volume explicitly using the `docker volume create` command, or Docker can + create a volume during container or service creation. + + When you create a volume, it is stored within a a directory on the Docker + host. When you mount the volume into a container, this directory is what is + mounted into the container. This is similar to the way that bind mounts work, + except that volumes are managed by Docker and are isolated from the core + functionality of the host machine. + + A given volume can be mounted into multiple containers simultaneously. When no + running container is using a volume, the volume is still available to Docker + and is not removed automatically. You can remove unused volumes using `docker + volume prune`. + + When you mount a volume, it may be **named** or **anonymous**. Anonymous + volumes are not given an explicit name when they are first mounted into a + container, so Docker gives them a random name that is guaranteed to be unique + within a given Docker host. Besides the name, named and anonymous volumes + behave in the same ways. + + Volumes also support the use of _volume drivers_, which allow you to store + your data on remote hosts or cloud providers, among other possibilities. + +- **[Bind mounts](bind-mounts.md)**: Available since the early days of Docker. + Bind mounts have limited functionality compared to volumes. When you use a + bind mount, a file or directory on the _host machine_ is mounted into a + container. The file or directory is referenced by its full path on the host + machine. The file or directory does not need to exist on the Docker host + already. It is created on demand if it does not yet exist. Bind mounts are + very performant, but they rely on the host machine's filesystem having a + specific directory structure available. If you are developing new Docker + applications, consider using named volumes instead. You can't use + Docker CLI commands to directly manage bind mounts. + + > **Warning**: One side effect of using bind mounts, for better or for worse, + > is that you can change the **host** filesystem via processes running in a + > **container**, including creating, modifying, or deleting important system + > files or directories. This is a powerful ability which can have security + > implications, including impacting non-Docker processes on the host system. + {: .warning } + +- **[tmpfs mounts](tmpfs.md)**: A `tmpfs` mount is not persisted on disk, either + on the Docker host or within a container. It can be used by a container during + the lifetime of the container, to store non-persistent state or sensitive + information. For instance, internally, swarm services use `tmpfs` mounts to + mount [secrets](/engine/swarm/secrets.md) into a service's containers. + +Bind mounts and volumes can both mounted into containers using the `-v` or +`--volume` flag, but the syntax for each is slightly different. For `tmpfs` +mounts, you can use the `--tmpfs` flag. However, in Docker 17.06 and higher, +we recommend using the `--mount` flag for both containers and services, for +bind mounts, volumes, or `tmpfs` mounts, as the syntax is more clear. + +## Good use cases for volumes + +Volumes are the preferred way to persist data in Docker containers and services. +Some use cases for volumes include: + +- Sharing data among multiple running containers. If you don't explicitly create + it, a volume is created the first time it is mounted into a container. When + that container stops or is removed, the volume still exists. Multiple + containers can mount the same volume simultaneously, either read-write or + read-only. Volumes are only removed when you explicitly remove them. + +- When the Docker host is not guaranteed to have a given directory or file + structure. Volumes help you decouple the configuration of the Docker host + from the container runtime. + +- When you want to store your container's data on a remote host or a cloud + provider, rather than locally. + +- When you need to be able to back up, restore, or migrate data from one Docker + host to another, volumes are a better choice. You can stop containers using + the volume, then back up the volume's directory + (such as `/var/lib/docker/volumes/`). + +## Good use cases for bind mounts + +In general, you should use volumes where possible. Bind mounts are appropriate +for the following types of use case: + +- Sharing configuration files from the host machine to containers. This is how + Docker provides DNS resolution to containers by default, by mounting + `/etc/resolv.conf` from the host machine into each container. + +- Sharing source code or build artifacts between a development environment on + the Docker host and a container. For instance, you may mount a Maven `target/` + directory into a container, and each time you build the Maven project on the + Docker host, the container gets access to the rebuilt artifacts. + + If you use Docker for development this way, your production Dockerfile would + copy the production-ready artifacts directly into the image, rather than + relying on a bind mount. + +- When the file or directory structure of the Docker host is guaranteed to be + consistent with the bind mounts the containers require. + +## Good use cases for tmpfs mounts + +`tmpfs` mounts are best used for cases when you do not want the data to persist +either on the host machine or within the container. This may be for security +reasons or to protect the performance of the container when your application +needs to write a large volume of non-persistent state data. + +## Tips for using bind mounts or volumes + +If you use either bind mounts or volumes, keep the following in mind: + +- If the container's image contains data at the mount point, this data will be + propagated into the bind mount or volume. This is a good way to pre-populate + data that the Docker host needs (in the case of bind mounts) or that another + container needs (in the case of volumes). + +- If you mount a bind mount or volume into a directory in the container in which + files or directories have already been written, these files or directories are + obscured by the mount, just as if you saved 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 were unmounted. + +## Next steps + +- Learn more about [volumes](volumes.md). +- Learn more about [bind mounts](bind-mounts.md). +- Learn more about [tmpfs mounts](tmpfs.md). +- Learn more about [storage drivers](/engine/userguide/storagedriver.md), which + are not related to bind mounts or volumes, but allow you to store data in a + container's writable layer. \ No newline at end of file diff --git a/engine/admin/volumes/tmpfs.md b/engine/admin/volumes/tmpfs.md new file mode 100644 index 0000000000..cb9b7a9430 --- /dev/null +++ b/engine/admin/volumes/tmpfs.md @@ -0,0 +1,144 @@ +--- +description: Using tmpfs mounts +title: Use tmpfs mounts +keywords: storage, persistence, data persistence, tmpfs +--- + +[Volumes](volumes.md) and [bind mounts](bind-mounts.md) are mounted into the +container's filesystem by default, and their contents are stored on on the host +machine. + +There may be cases where you do not want to store a container's data on the host +machine, but you also don't want to write the data into the container's writable +layer, for performance or security reasons, or if the data relates to +non-persistent application state. An example might be a temporary one-time +password that the container's application creates and uses as-needed. + +To give the container access to the data without writing it anywhere +permanently, you can use a `tmpfs` mount, which is only stored in the host +machine's memory (or swap, if memory is low). When the container stops, the +`tmpfs` mount is removed. If a container is committed, the `tmpfs` mount is not +saved. + +## Choosing the --tmpfs or --mount flag + +Originally, the `--tmpfs` flag was used for standalone containers and +the `--mount` flag was used for swarm services. However, starting with Docker +17.06, you can also use `--mount` with standalone containers. In general, +`--mount` is more explicit and verbose. The biggest difference is that the +`--tmpfs` flag does not support any configurable options. + +> **Tip**: New users should use the `--mount` syntax. Experienced users may +> be more familiar with the `--tmpfs` syntax, but are encouraged to +> use `--mount`, because research has shown it to be easier to use. + +- **`--tmpfs`**: Mounts a `tmpfs` mount without allowing you to specify any + configurable options, and can only be used with standalone containers. + +- **`--mount`**: Consists of multiple key-value pairs, separated by commas and each + consisting of a `=` tuple. The `--mount` syntax is more verbose + than `-v` or `--volume`, but the order of the keys is not significant, and + the value of the flag is easier to understand. + - The `type` of the mount, which can be [`bind`](bind-mounts-md), `volume`, or + [`tmpfs`](tmpfs.md). This topic discusses `tmpfs`, so the type will always + be `tmpfs`. + - The `destination` takes as its value the path where the `tmpfs` mount + will be mounted in the container. May be specified as `destination`, `dst`, + or `target`. + - The `tmpfs-type` and `tmpfs-mode` options. See + [tmpfs options](#tmpfs-options). + +The examples below show both the `--mount` and `--tmpfs` syntax where possible, +and `--mount` is presented first. + +### Differences between `--tmpfs` and `--mount` behavior + +- The `--tmpfs` flag does not allow you to specify any configurable options. +- The `--tmpfs` flag cannot be used with swarm services. You must use `--mount`. + +## Limitations of tmpfs containers + +- `tmpfs` mounts cannot be shared among containers. +- `tmpfs` mounts only work on Linux containers, and not on Windows containers. + +## Use a tmpfs mount in a container + +To use a `tmpfs` mount in a container, use the `--tmpfs` flag, or use the +`--mount` flag with `type=tmpfs` and `destination` options. There is no +`source` for `tmpfs` mounts. The following example creates a `tmpfs` mount at +`/app` in a Nginx container. The first example uses the `--mount` flag and the +second uses the `--tmpfs` flag. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name tmptest \ + --mount type=tmpfs,destination=/app \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name tmptest \ + --tmpfs /app \ + nginx:latest +``` + +
+
+ +Verify that the mount is a `tmpfs` mount by running `docker container inspect +tmptest` and looking for the `Mounts` section: + +```json +"Tmpfs": { + "/app": "" +}, +``` + +Remove the container: + +```bash +$ docker container stop tmptest + +$ Docker container rm tmptest +``` + +### Specify tmpfs options + +`tmpfs` mounts allow for two configuration options, neither of which is +required. If you need to specify these options, you must use the `--mount` flag, +as the `--tmpfs` flag does not support them. + +| Option | Description | +|:-------------|:------------------------------------------------------------------------------------------------------| +| `tmpfs-size` | Size of the tmpfs mount in bytes. Unlimited by default. | +| `tmpfs-mode` | File mode of the tmpfs in octal. For instance, `700` or `0770`. Defaults to `1777` or world-writable. | + +The following example sets the `tmpfs-mode` to `1770`, so that it is not +world-readable within the container. + +```bash +docker run -d \ + -it \ + --name tmptest \ + --mount type=tmpfs,destination=/app,tmpfs-mode=1770 \ + nginx:latest +``` + +## Next steps + +- Learn about [volumes](volumes.md) +- Learn about [bind mounts](bind-mounts.md) +- Learn about [storage drivers](/engine/userguide/storagedriver.md) \ No newline at end of file diff --git a/engine/admin/volumes/volumes.md b/engine/admin/volumes/volumes.md new file mode 100644 index 0000000000..e10c38719a --- /dev/null +++ b/engine/admin/volumes/volumes.md @@ -0,0 +1,384 @@ +--- +description: Using volumes +title: Use volumes +keywords: storage, persistence, data persistence, volumes +redirect_from: +- engine/tutorials/dockervolumes/ +--- + +Volumes are the preferred mechanism for persisting data generated by and used +by Docker containers. While [bind mounts](bind-mounts.md) are dependent on the +directory structure of the host machine, volumes are completely managed by +Docker. Volumes have several advantages over bind mounts: + +- Volumes are easier to back up or migrate than bind mounts. +- You can manage volumes using Docker CLI commands or the Docker API. +- Volumes work on both Linux and Windows containers. +- Volumes can be more safely shared among multiple containers. +- Volume drivers allow you to store volumes on remote hosts or cloud providers, + to encrypt the contents of volumes, or to add other functionality. +- A new volume's contents can be pre-populated by a container. + +In addition, volumes are often a better choice than persisting data in a +container's writable layer, because using a volume does not increase the size of +containers using it, and the volume's contents exist outside the lifecycle of a +given container. + +If your container generates non-persistent state data, consider using a +[tmpfs mount](tmpfs.md) to avoid storing the data anywhere permanently, and to +increase the container's performance by avoiding writing into the container's +writable layer. + +Volumes use `rprivate` bind propagation, and bind propagation is not +configurable for volumes. + +## Choosing the -v or --mount flag + +Originally, the `-v` or `--volume` flag was used for standalone containers and +the `--mount` flag was used for swarm services. However, starting with Docker +17.06, you can also use `--mount` with standalone containers. In general, +`--mount` is more explicit and verbose. The biggest difference is that the `-v` +syntax combines all the options together in one field, while the `--mount` +syntax separates them. Here is a comparison of the syntax for each flag. + +> **Tip**: New users should use the `--mount` syntax. Experienced users may +> be more familiar with the `-v` or `--volume` syntax, but are encouraged to +> use `--mount`, because research has shown it to be easier to use. + +If you need to specify volume driver options, you must use `--mount`. + +- **`-v` or `--volume`**: Consists of three fields, separated by colon characters + (`:`). The fields must be in the correct order, and the meaning of each field + is not immediately obvious. + - In the case of named volumes, the first field is the name of the volume, and is + unique on a given host machine. For anonymous volumes, the first field is + omitted. + - The second field is the path where the file or directory will be mounted in + the container. + - The third field is optional, and is a comma-separated list of options, such + as `ro`. These options are discussed below. + +- **`--mount`**: Consists of multiple key-value pairs, separated by commas and each + consisting of a `=` tuple. The `--mount` syntax is more verbose + than `-v` or `--volume`, but the order of the keys is not significant, and + the value of the flag is easier to understand. + - The `type` of the mount, which can be [`bind`](bind-mounts-md), `volume`, or + [`tmpfs`](tmpfs.md). This topic discusses volumes, so the type will always + be `volume`. + - The `source` of the mount. For named volumes, this is the name of the volume. + For anonymous volumes, this field is omitted. May be specified as `source` + or `src`. + - The `destination` takes as its value the path where the file or directory + will be mounted in the container. May be specified as `destination`, `dst`, + or `target`. + - The `readonly` option, if present, causes the bind mount to be [mounted into + the container as read-only](#use-a-read-only-bind-mount). + - The `volume-opt` option, which can be specified more than once, takes a + key-value pair consisting of the option name and its value. + +The examples below show both the `--mount` and `-v` syntax where possible, and + `--mount` is presented first. + +### Differences between `-v` and `--mount` behavior + +As opposed to bind mounts, all options for volumes are available for both +`--mount` and `-v` flags. + +## Create and manage volumes + +Unlike a bind mount, you can create and manage volumes outside the scope of any +container. + +**Create a volume**: + +```bash +$ docker volume create my-vol +``` + +**List volumes**: + +```bash +$ docker volume ls + +local my-vol +``` + +**Inspect a volume**: + +```bash +$ docker volume inspect my-vol +[ + { + "Driver": "local", + "Labels": {}, + "Mountpoint": "/var/lib/docker/volumes/my-vol/_data", + "Name": "my-vol", + "Options": {}, + "Scope": "local" + } +] +``` + +**Remove a volume**: + +```bash +$ docker volume rm my-vol +``` + +## Start a container with a volume + +If you start a container with a volume that does not yet exist, Docker creates +the volume for you. The following example mounts the volume `myvol2` into +`/app/` in the container. + +The `-v` and `--mount` examples below produce the same result. You can't run +them both unless you remove the `devtest` container and the `myvol2` volume +after running the first one. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + --mount source=myvol2,target=/app \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name devtest \ + -v myvol2:/app \ + nginx:latest +``` + +
+
+ +Use `docker inspect devtest` to verify that the volume was created and mounted +correctly. Look for the `Mounts` section: + +```json +"Mounts": [ + { + "Type": "volume", + "Name": "myvol2", + "Source": "/var/lib/docker/volumes/myvol2/_data", + "Destination": "/app", + "Driver": "local", + "Mode": "", + "RW": true, + "Propagation": "" + } +], +``` + +This shows that the mount is a volume, it shows the correct source and +destination, and that the mount is read-write. + +Stop the container and remove the volume. + +```bash +$ docker container stop devtest + +$ docker container rm devtest + +$ docker volume rm myvol2 +``` + +### Syntax differences for services + +The `docker service create` command does not support the `-v` or `--volume` flag. +When mounting a volume into a service's containers, you must use the `--mount` +flag. + +### Populating a volume using a container + +If you start a container which creates a new volume, as above, and the container +has files or directories in the directory to be mounted (such as `/app/` above), +the directory's contents will be copied into the volume. The container will then +mount and use the volume, and other containers which use the volume will also +have access to the pre-populated content. + +To illustrate this, this example starts an `nginx` container and populates the +new volume `nginx-vol` with the contents of the container's +`/usr/share/nginx/html` directory, which is where Nginx stores its default HTML +content. + +The `--mount` and `-v` examples have the same end result. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name=nginxtest \ + --mount source=nginx-vol,destination=/usr/share/nginx/html \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name=nginxtest \ + -v nginx-vol:/usr/share/nginx/html \ + nginx:latest +``` + +
+
+ +After running either of these examples, run the following commands to clean up the +containers and volumes. + +```bash +$ docker container stop devtest + +$ docker container rm devtest + +$ docker volume rm nginx-vol +``` + +## Use a read-only volume + +For some development applications, it is useful for the container to be able to +write into the bind mount, in order for changes to be propagated back to the +Docker host. At other times, the container should only be able to read the +data and not modify it. Remember that multiple containers can mount the same +volume, and it can be mounted read-write for some of them and read-only for +others, simultaneously. + +This example modifies the one above but mounts the directory as a read-only +volume, by adding `ro` to the (empty by default) list of options, after the +mount point within the container. Where multiple options are present, separate +them by commas. + +The `--mount` and `-v` examples have the same result. + + +
+
+ +```bash +$ docker run -d \ + -it \ + --name=nginxtest \ + --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \ + nginx:latest +``` + +
+
+ +```bash +$ docker run -d \ + -it \ + --name=nginxtest \ + -v nginx-vol:/usr/share/nginx/html:ro \ + nginx:latest +``` + +
+
+ +Use `docker inspect nginxtest` to verify that the bind mount was created +correctly. Look for the `Mounts` section: + +```json +"Mounts": [ + { + "Type": "volume", + "Name": "nginx-vol", + "Source": "/var/lib/docker/volumes/nginx-vol/_data", + "Destination": "/usr/share/nginx/html", + "Driver": "local", + "Mode": "", + "RW": false, + "Propagation": "" + } +], +``` + +Stop and remove the container, and remove the volume: + +```bash +$ docker container stop devtest + +$ docker container rm devtest + +$ docker volume rm nginx-vol +``` + +## Use a volume driver + +When you create a volume using `docker volume create`, or when you start a +container which uses a not-yet-created volume, you can specify a volume driver. +The following examples use the `vieux/sshfs` volume driver, first when creating +a standalone volume, and then when starting a container which will create a new +volume. + +### Initial set-up + +This example assumes that you have two nodes, the first of which is a Docker +host and can connect to the second using SSH. + +On the Docker host, install the `vieux/sshfs` plugin: + +```bash +$ docker plugin install --grant-all-permissions vieux/sshfs +``` + +### Create a volume using a volume driver + +This example specifies a SSH password, but if the two hosts have shared keys +configured, you can omit the password. Each volume driver may have zero or more +configurable options, each of which is specified using an `-o` flag. + +```bash +$ docker volume create --driver vieux/sshfs \ + -o sshcmd=test@node2:/home/test \ + -o password=testpassword \ + sshvolume +``` + +### Start a container which creates a volume using a volume driver + +This example specifies a SSH password, but if the two hosts have shared keys +configured, you can omit the password. Each volume driver may have zero or more +configurable options. **If the volume driver requires you to pass options, you +must use the `--mount` flag to mount the volume, rather than `-v`.** + +```bash +$ docker run -d \ + --it \ + --name sshfs-container \ + --volume-driver vieux/sshfs \ + --mount src=sshvolume,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \ + nginx:latest +``` + +## Next steps + +- Learn about [bind mounts](bind-mounts.md). +- Learn about [tmpfs mounts](tmpfs.md). +- Learn about [storage drivers](/engine/userguide/storagedriver.md). \ No newline at end of file diff --git a/engine/tutorials/dockervolumes.md b/engine/tutorials/dockervolumes.md deleted file mode 100644 index e8bd2e54fb..0000000000 --- a/engine/tutorials/dockervolumes.md +++ /dev/null @@ -1,394 +0,0 @@ ---- -description: How to manage data inside your Docker containers. -keywords: Examples, Usage, volume, docker, documentation, user guide, data, volumes -redirect_from: -- /engine/userguide/containers/dockervolumes/ -- /engine/userguide/dockervolumes/ -- /userguide/dockervolumes/ -title: Manage data in containers ---- - -In this section you're going to learn how you can manage data inside and between -your Docker containers. - -You're going to look at the two primary ways you can manage data with -Docker Engine. - -* Data volumes -* Data volume containers - -## Data volumes - -A *data volume* is a specially-designated directory within one or more -containers that bypasses the [*Union File System*](/glossary/?term=Union file system). -Data volumes provide several useful features for persistent or shared data: - -- Volumes are initialized when a container is created. If the container's - parent image contains data at the specified mount point, that existing data is - copied into the new volume upon volume initialization. (Note that this does - not apply when [mounting a host directory](#mount-a-host-file-as-a-data-volume).) -- Data volumes can be shared and reused among containers. -- Changes to a data volume are made directly. -- Changes to a data volume will not be included when you update an image. -- Data volumes persist even if the container itself is deleted. - -Data volumes are designed to persist data, independent of the container's lifecycle. -Docker therefore *never* automatically deletes volumes when you remove -a container, nor will it "garbage collect" volumes that are no longer -referenced by a container. - -### Add a data volume - -You can add a data volume to a container using the `-v` flag with the -`docker create` and `docker run` command. You can use the `-v` multiple times -to mount multiple data volumes. Now, mount a single volume in your web -application container. - -```bash -$ docker run -d -P --name web -v /webapp training/webapp python app.py -``` - -This will create a new volume inside a container at `/webapp`. - -> **Note**: -> You can also use the `VOLUME` instruction in a `Dockerfile` to add one or -> more new volumes to any container created from that image. - -### Locate a volume - -You can locate the volume on the host by utilizing the `docker inspect` command. - -```bash -$ docker inspect web -``` - -The output will provide details on the container configurations including the -volumes. The output should look something similar to the following: - -```json -... -"Mounts": [ - { - "Name": "fac362...80535", - "Source": "/var/lib/docker/volumes/fac362...80535/_data", - "Destination": "/webapp", - "Driver": "local", - "Mode": "", - "RW": true, - "Propagation": "" - } -] -... -``` - -You will notice in the above `Source` is specifying the location on the host and -`Destination` is specifying the volume location inside the container. `RW` shows -if the volume is read/write. - -### Mount a host directory as a data volume - -In addition to creating a volume using the `-v` flag you can also mount a -directory from your Docker engine's host into a container. - -```bash -$ docker run -d -P --name web -v /src/webapp:/webapp training/webapp python app.py -``` - -This command mounts the host directory, `/src/webapp`, into the container at -`/webapp`. If the path `/webapp` already exists inside the container's -image, the `/src/webapp` mount overlays but does not remove the pre-existing -content. Once the mount is removed, the content is accessible again. This is -consistent with the expected behavior of the `mount` command. - -The `container-dir` must always be an absolute path such as `/src/docs`. -The `host-dir` can either be an absolute path such as `/dst/docs` on Linux -or `C:\dst\docs` on Windows, or a `name` value. If you -supply an absolute path for the `host-dir`, Docker bind-mounts to the path -you specify. If you supply a `name`, Docker creates a named volume by that `name`. - -A `name` value must start with an alphanumeric character, -followed by `a-z0-9`, `_` (underscore), `.` (period) or `-` (hyphen). -An absolute path starts with a `/` (forward slash). - -For example, you can specify either `/foo` or `foo` for a `host-dir` value. -If you supply the `/foo` value, the Docker Engine creates a bind-mount. If you supply -the `foo` specification, the Docker Engine creates a named volume. - -If you are using Docker Machine on Mac or Windows, your Docker Engine daemon has only -limited access to your macOS or Windows filesystem. Docker Machine tries to -auto-share your `/Users` (macOS) or `C:\Users` (Windows) directory. So, you can -mount files or directories on macOS using. - -```bash -docker run -v /Users/:/ ... -``` - -On Windows, mount directories using: - -```bash -docker run -v c:\:c:\ -``` - -All other paths come from your virtual machine's filesystem, so if you want -to make some other host folder available for sharing, you need to do -additional work. In the case of VirtualBox you need to make the host folder -available as a shared folder in VirtualBox. Then, you can mount it using the -Docker `-v` flag. - -Mounting a host directory can be useful for testing. For example, you can mount -source code inside a container. Then, change the source code and see its effect -on the application in real time. The directory on the host must be specified as -an absolute path and if the directory doesn't exist the Docker Engine daemon -automatically creates it for you. - -Docker volumes default to mount in read-write mode, but you can also set it to -be mounted read-only. - -```bash -$ docker run -d -P --name web -v /src/webapp:/webapp:ro training/webapp python app.py -``` - -Here you've mounted the same `/src/webapp` directory but you've added the `ro` -option to specify that the mount should be read-only. - -You can also relax the consistency requirements of a mounted directory -to improve performance by adding the `cached` option: - -```bash -$ docker run -d -P --name web -v /src/webapp:/webapp:cached training/webapp python app.py -``` - -The `cached` option typically improves the performance of read-heavy workloads -on Docker for Mac, at the cost of some temporary inconsistency between the host -and the container. On other platforms, `cached` currently has no effect. The -article [User-guided caching in Docker for -Mac](https://blog.docker.com/2017/05/user-guided-caching-in-docker-for-mac/) -gives more details about the behavior of `cached` on macOS. - - ->**Note**: The host directory is, by its nature, host-dependent. For this ->reason, you can't mount a host directory from `Dockerfile`, the `VOLUME` -instruction does not support passing a `host-dir`, because built images ->should be portable. A host directory wouldn't be available on all potential ->hosts. - - -### Mount a shared-storage volume as a data volume - -In addition to mounting a host directory in your container, some Docker -[volume plugins](/engine/extend/plugins_volume.md) allow you to -provision and mount shared storage, such as iSCSI, NFS, or FC. - -A benefit of using shared volumes is that they are host-independent. This -means that a volume can be made available on any host that a container is -started on as long as it has access to the shared storage backend, and has -the plugin installed. - -One way to use volume drivers is through the `docker run` command. -Volume drivers create volumes by name, instead of by path like in -the other examples. - -The following command creates a named volume, called `my-named-volume`, -using the `convoy` volume driver (`convoy` is a plugin for a variety of storage back-ends) -and makes it available within the container at `/webapp`. Before running the command, -[install and configure convoy](https://github.com/rancher/convoy#quick-start-guide). -If you do not want to install `convoy`, replace `convoy` with `local` in the example commands -below to use the `local` driver. - -```bash -$ docker run -d -P \ - --volume-driver=convoy \ - -v my-named-volume:/webapp \ - --name web training/webapp python app.py -``` - -You may also use the `docker volume create` command, to create a volume before -using it in a container. - -The following example also creates the `my-named-volume` volume, this time -using the `docker volume create` command. Options are specified as key-value -pairs in the format `o==`. - -```bash -$ docker volume create -d convoy --opt o=size=20GB my-named-volume - -$ docker run -d -P \ - -v my-named-volume:/webapp \ - --name web training/webapp python app.py -``` - -A list of available plugins, including volume plugins, is available -[here](/engine/extend/legacy_plugins.md). - -### Volume labels - -Labeling systems like SELinux require that proper labels are placed on volume -content mounted into a container. Without a label, the security system might -prevent the processes running inside the container from using the content. By -default, Docker does not change the labels set by the OS. - -To change a label in the container context, you can add either of two suffixes -`:z` or `:Z` to the volume mount. These suffixes tell Docker to relabel file -objects on the shared volumes. The `z` option tells Docker that two containers -share the volume content. As a result, Docker labels the content with a shared -content label. Shared volume labels allow all containers to read/write content. -The `Z` option tells Docker to label the content with a private unshared label. -Only the current container can use a private volume. - -### Mount a host file as a data volume - -The `-v` flag can also be used to mount a single file - instead of *just* -directories - from the host machine. - -```bash -$ docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bash -``` - -This will drop you into a bash shell in a new container, you will have your bash -history from the host and when you exit the container, the host will have the -history of the commands typed while in the container. - -> **Note**: -> Many tools used to edit files including `vi` and `sed --in-place` may result -> in an inode change. Since Docker v1.1.0, this will produce an error such as -> "*sed: cannot rename ./sedKdJ9Dy: Device or resource busy*". In the case where -> you want to edit the mounted file, it is often easiest to instead mount the -> parent directory. - -## Creating and mounting a data volume container - -If you have some persistent data that you want to share between -containers, or want to use from non-persistent containers, it's best to -create a named Data Volume Container, and then to mount the data from -it. - -Let's create a new named container with a volume to share. -While this container doesn't run an application, it reuses the `training/postgres` -image so that all containers are using layers in common, saving disk space. - -```bash -$ docker create -v /dbdata --name dbstore training/postgres /bin/true -``` - -You can then use the `--volumes-from` flag to mount the `/dbdata` volume in another container. - -```bash -$ docker run -d --volumes-from dbstore --name db1 training/postgres -``` - -And another: - -```bash -$ docker run -d --volumes-from dbstore --name db2 training/postgres -``` - -In this case, if the `postgres` image contained a directory called `/dbdata` -then mounting the volumes from the `dbstore` container hides the -`/dbdata` files from the `postgres` image. The result is only the files -from the `dbstore` container are visible. - -You can use multiple `--volumes-from` parameters to combine data volumes from -several containers. To find detailed information about `--volumes-from` see the -[Mount volumes from container](/engine/reference/commandline/run.md#mount-volumes-from-container-volumes-from) -in the `run` command reference. - -You can also extend the chain by mounting the volume that came from the -`dbstore` container in yet another container via the `db1` or `db2` containers. - -```bash -$ docker run -d --name db3 --volumes-from db1 training/postgres -``` - -If you remove containers that mount volumes, including the initial `dbstore` -container, or the subsequent containers `db1` and `db2`, the volumes will not -be deleted. To delete the volume from disk, you must explicitly call -`docker rm -v` against the last container with a reference to the volume. This -allows you to upgrade, or effectively migrate data volumes between containers. - -> **Note**: Docker will not warn you when removing a container *without* -> providing the `-v` option to delete its volumes. If you remove containers -> without using the `-v` option, you may end up with "dangling" volumes; -> volumes that are no longer referenced by a container. -> You can use `docker volume ls -f dangling=true` to find dangling volumes, -> and use `docker volume rm ` to remove a volume that's -> no longer needed. - -## Backup, restore, or migrate data volumes - -Another useful function we can perform with volumes is use them for -backups, restores or migrations. You do this by using the -`--volumes-from` flag to create a new container that mounts that volume, -like so: - -```bash -$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata -``` - -Here you've launched a new container and mounted the volume from the -`dbstore` container. You've then mounted a local host directory as -`/backup`. Finally, you've passed a command that uses `tar` to backup the -contents of the `dbdata` volume to a `backup.tar` file inside our -`/backup` directory. When the command completes and the container stops -we'll be left with a backup of our `dbdata` volume. - -You could then restore it to the same container, or another that you've made -elsewhere. Create a new container. - -```bash -$ docker run -v /dbdata --name dbstore2 ubuntu /bin/bash -``` - -Then un-tar the backup file in the new container`s data volume. - -```bash -$ docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1" -``` - -You can use the techniques above to automate backup, migration and -restore testing using your preferred tools. - -## List all volumes - -You can list all existing volumes using `docker volume ls`. - -```bash -$ docker volume ls -DRIVER VOLUME NAME -local ec75c47aa8b8c61fdabcf37f89dad44266841b99dc4b48261a4757e70357ec06 -local f73e499de345187639cdf3c865d97f241216c2382fe5fa67555c64f258892128 -local tmp_data -``` - -## Remove volumes - -A Docker data volume persists after a container is deleted. You can create named -or anonymous volumes. Named volumes have a specific source form outside the -container, for example `awesome:/bar`. Anonymous volumes have no specific -source. When the container is deleted, you should instruct the Docker Engine daemon -to clean up anonymous volumes. To do this, use the `--rm` option, for example: - -```bash -$ docker run --rm -v /foo -v awesome:/bar busybox top -``` - -This command creates an anonymous `/foo` volume. When the container is removed, -the Docker Engine removes the `/foo` volume but not the `awesome` volume. - -To remove all unused volumes and free up space, - -```bash -$ docker volume prune -``` - -it will remove all unused volumes which are not associated with any container. - -## Important tips on using shared volumes - -Multiple containers can also share one or more data volumes. However, multiple -containers writing to a single shared volume can cause data corruption. Make -sure your applications are designed to write to shared data stores. - -Data volumes are directly accessible from the Docker host. This means you can -read and write to them with normal Linux tools. In most cases you should not do -this as it can cause data corruption if your containers and applications are -unaware of your direct access.