Persistent Storage¶
New
Introduced in 0.5.0. Named storage entries introduced in 0.38.0.
The preferred method to attach persistent storage to a Dokku-managed container is the Dokku storage plugin.
storage:create <name> [<path>] [flags] # Register a named storage entry
storage:destroy <name> # Remove a named storage entry (must be unmounted from every app first)
storage:ensure-directory [--chown option] <directory> # [DEPRECATED] use storage:create instead
storage:exec <name> [-- <cmd>...] # Run a command (or shell) in a temporary container that mounts the entry
storage:info <name> [--format text|json] # Show details for one storage entry
storage:list <app> [--format text|json] # List bind mounts for an app's container(s) (legacy host:container view)
storage:list-entries [--scheduler s] [--format text|json] # List registered storage entries
storage:mount <app> <name> --container-dir <path> [flags] # Mount a named entry into an app
storage:mount <app> <host-dir:container-dir> # [LEGACY] colon-form mount, docker-local only
storage:report [<app>] [<flag>] # Display a storage report for one or more apps
storage:report --global # Display a cluster-wide entry inventory
storage:set <name> [flags] # Update a storage entry in place
storage:unmount <app> <name> [--container-dir <path>] # Remove an attachment
storage:wait <name> # Block until a k3s entry's PVC is bound
A storage entry is the source of truth for the underlying volume - a host directory on docker-local, or a PersistentVolumeClaim on k3s. Multiple apps can mount the same entry, and an attachment carries the per-app details (container path, phases, subpath, readonly, process type). Names are globally unique across the install and must be DNS-1123 labels (lowercase letters, digits, dashes) of 45 characters or less so they can be used verbatim as Helm release and PVC names.
The legacy storage:mount <app> <host>:<container> form continues to work on docker-local. On a k3s app it is rejected; create a named entry with storage:create --scheduler k3s and mount it instead. Existing colon-form mounts are migrated automatically the first time the new code runs - they show up as legacy-<hash> entries in storage:list-entries.
The storage plugin supports the following mount points:
- explicit paths that exist on the host (docker-local)
- docker volumes (docker-local)
- PersistentVolumeClaims provisioned via a StorageClass (k3s)
- hostPath-backed PVs (k3s)
Usage¶
Listing persistent storage¶
Persistent storage bind mounts are specified on a per-app basis, and can be listed with the storage:list command:
The output format can also be set to json for programmatic access:
Creating storage directories¶
New
Introduced in 0.25.5
A storage directory can be created with the storage:ensure-directory command. This command will create a subdirectory in the recommended /var/lib/dokku/data/storage path - created during Dokku installation - and prepare it for use with an app.
By default, permissions are set for usage with Herokuish buildpacks. These permissions can be changed via the --chown option according to the following table:
--chown herokuish(default): Use32767:32767as the folder permissions.- This is used for apps deployed with Buildpacks via Herokuish.
--chown heroku: Use1000:1000as the folder permissions.- This is used for apps deployed with Cloud Native Buildpacks using the
heroku/builderbuilder.
- This is used for apps deployed with Cloud Native Buildpacks using the
--chown paketo: Use2000:2000as the folder permissions.- This is used for apps deployed with Cloud Native Buildpacks using the
cloudfoundry/cnborpaketobuilders.
- This is used for apps deployed with Cloud Native Buildpacks using the
--chown root: Use0:0as the folder permissions.- This is used for containers that run their processes as root, as is typical for most Dockerfile or Docker image deploys.
--chown false: Skips thechowncall.
Users deploying via Dockerfile will want to specify --chown false and manually chown the created directory if the user and/or group id of the runnning process in the deployed container do not correspond to any of the above options.
Warning
Failing to set the correct directory ownership may result in issues in persisting files written to the mounted storage directory.
Mounting storage into apps¶
Dokku supports mounting both explicit host paths as well as docker volumes via the storage:mount command. This takes two arguments, an app name and a host-path:container-path or docker-volume:container-path combination.
# mount the directory into your container's /app/storage directory, relative to the container root (/)
# explicit host paths _must_ exist prior to usage.
dokku storage:mount node-js-app /var/lib/dokku/data/storage/node-js-app:/app/storage
# mount the docker volume into your container's /app/storage directory, relative to the container root (/)
# docker volumes _must_ exist prior to usage.
dokku storage:mount node-js-app some-docker-volume:/app/storage
In the first example, Dokku will then mount the shared contents of /var/lib/dokku/data/storage/node-js-app to /app/storage inside the container. The mount point is not relative to your app's working directory, and is instead relative to the root (/) of the container. Mounts are only available for containers created via run and by the deploy process, and not during the build process. In addition, the host path is never auto-created by either Dokku or Docker, and should be an explicit path, not one relative to the current working directory.
Info
If the /storage path within the container had pre-existing content, the container files will be over-written. This may be an issue for users that create assets at build time but then mount a directory at the same place during runtime. Files are not merged.
Once persistent storage is mounted, the app requires a restart. See the process scaling documentation for more information.
Unmounting storage¶
If an app no longer requires a mounted volume or directory, the storage:unmount command can be called. This takes the same arguments as the storage:mount command, an app name and a host-path:container-path or docker-volume:container-path combination.
# unmount the directory from your container's /app/storage directory, relative to the container root (/)
dokku storage:unmount node-js-app /var/lib/dokku/data/storage/node-js-app:/app/storage
# unmount the docker volume from your container's /app/storage directory, relative to the container root (/)
dokku storage:unmount node-js-app some-docker-volume:/app/storage
Once persistent storage is unmounted, the app requires a restart. See the process scaling documentation for more information.
Displaying storage reports for an app¶
New
Introduced in 0.8.1
You can get a report about the app's storage status using the storage:report command:
=====> node-js-app storage information
Storage build mounts:
Storage deploy mounts: -v /var/lib/dokku/data/storage/node-js-app:/app/storage
Storage run mounts: -v /var/lib/dokku/data/storage/node-js-app:/app/storage
=====> python-sample storage information
Storage build mounts:
Storage deploy mounts:
Storage run mounts:
=====> ruby-sample storage information
Storage build mounts:
Storage deploy mounts:
Storage run mounts:
You can run the command for a specific app also.
You can pass flags which will output only the value of the specific information you want. For example:
Use Cases¶
Sharing storage across deploys¶
Dokku is powered by Docker containers, which recommends in their best practices that containers be treated as ephemeral. In order to manage persistent storage for web apps, like user uploads or large binary assets like images, a directory outside the container should be mounted.
Shared storage between containers¶
When scaling your app, you may require a common location to access shared assets between containers, a storage mount can be used in this situation.
Shared storage across environments¶
Your app may be used in a cluster that requires containers or resources not running on the same host access your data. Mounting a shared file service (like S3FS or EFS) inside your container will give you great flexibility.
Backing up¶
Your app may have services that are running in memory and need to be backed up locally (like a key store). Mount a non ephemeral storage mount will allow backups that are not lost when the app is shut down.
Build phase¶
By default, Dokku will only bind storage mounts during the deploy and run phases. Under certain conditions, one might want to bind a storage mount during the build phase. This can be accomplished by using the docker-options plugin directly.
You cannot use mounted volumes during the build phase of a Dockerfile deploy. This is because Docker does not support volumes when executing docker build.
Warning
This can cause data loss if you bind a mount under /app in buildpack apps as herokuish will attempt to remove the original app path during the build phase.
App User and Persistent Storage file ownership (buildpack apps only)¶
New
Introduced in 0.7.1
By default, Dokku will execute your buildpack app processes as the herokuishuser user. You may override this by setting the DOKKU_APP_USER config variable.
Note
this user must exist in your herokuish image.
Additionally, the default docker-local scheduler that comes with Dokku will ensure your storage mounts are owned by either herokuishuser or the overridden value you have set in DOKKU_APP_USER. See the docker-local scheduler documentation docs for more information.