Merge pull request #4809 from dokku/4805-ensure-directory

Implement storage:ensure-directory command
This commit is contained in:
Jose Diaz-Gonzalez
2021-09-30 01:25:33 -04:00
committed by GitHub
7 changed files with 266 additions and 36 deletions

View File

@@ -5,10 +5,11 @@
The preferred method to mount external containers to a Dokku managed container, is to use the Dokku storage plugin.
```
storage:list <app> # List bind mounts for app's container(s) (host:container)
storage:mount <app> <host-dir:container-dir> # Create a new bind mount
storage:report [<app>] [<flag>] # Displays a checks report for one or more apps
storage:unmount <app> <host-dir:container-dir> # Remove an existing bind mount
storage:ensure-directory [--chown option] <directory> # Creates a persistent storage directory in the recommended storage path
storage:list <app> # List bind mounts for app's container(s) (host:container)
storage:mount <app> <host-dir:container-dir> # Create a new bind mount
storage:report [<app>] [<flag>] # Displays a checks report for one or more apps
storage:unmount <app> <host-dir:container-dir> # Remove an existing bind mount
```
> The storage plugin is compatible with storage mounts created with the docker-options. The storage plugin will only list mounts from the deploy/run phase.
@@ -20,50 +21,77 @@ The storage plugin supports the following mount points:
## Usage
This example demonstrates how to mount the recommended directory to `/storage` inside an application called `node-js-app`. For simplicity, the Dokku project recommends using the directory `/var/lib/dokku/data/storage` directory as the root host path for mounts. This directory is created on Dokku installation.
### Creating storage directories
> New as of 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/doku/data/storage` path - created during Dokku installation - and prepare it for use with an app.
```shell
# we use a subdirectory inside of the host directory to scope it to just the app
dokku storage:mount node-js-app /var/lib/dokku/data/storage/node-js-app:/storage
dokku storage:ensure-directory lollipop
```
Dokku will then mount the shared contents of `/var/lib/dokku/data/storage/node-js-app` to `/storage` inside the container. Mounts are only available for containers crated 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.
```
-----> Ensuring /var/lib/dokku/data/storage/lollipop exists
Setting directory ownership to 32767:32767
Directory ready for mounting
```
> If the `/storage` path within the container had pre-existing content, the container files will be overrwritten. 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.
By default, permissions are set for usage with Herokuish buildpacks. These permissions can be changed via the `--chown` option according to the following table:
Once you have mounted persistent storage, you will also need to restart the application. See the
[process scaling documentation](/docs/processes/process-management.md) for more information.
- `--chown herokuish` (default): Use `32767:32767` as the folder permissions.
- This is used for apps deployed with Buildpacks via Herokuish.
- `--chown heroku`: Use `1000:1000` as the folder permissions.
- This is used for apps deployed with Cloud Native Buildpacks using the `heroku/buildpacks` builder.
- `--chown packeto`: Use `2000:2000` as the folder permissions.
- This is used for apps deployed with Cloud Native Buildpacks using the `cloudfoundry/cnb` or `packeto` builders.
- `--chown false`: Skips the `chown` call.
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.
```shell
# 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.
> 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](/docs/processes/process-management.md) for more information.
```shell
dokku ps:restart app-name
```
A more complete workflow may require making a custom directory for your application and mounting it within your `/app/storage` directory instead. The mount point is *not* relative to your application's working directory, and is instead relative to the root (`/`) of the container.
### 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.
```shell
# creating storage for the app 'node-js-app'
mkdir -p /var/lib/dokku/data/storage/node-js-app
# 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
# set the directory ownership. Below is an example for herokuish
# but see the `Directory Permissions` section for more details
chown -R 32767:32767 /var/lib/dokku/data/storage/node-js-app
# mount the directory into your container's /app/storage directory, relative to root
dokku storage:mount app-name /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
```
You can mount one or more directories as desired by following the above pattern.
Once persistent storage is unmounted, the app requires a restart. See the [process scaling documentation](/docs/processes/process-management.md) for more information.
### Directory Permissions
The host directory should always be owned by the container user and group id. If this is not the case, files may not persist when written to mounted storage.
- Buildpacks via Herokuish: Use `32767:32767` as the file permissions
- For Cloud Native Buildpacks: This will depend on the builder in question, but can be retrieved via the `CNB_USER_ID` and `CNB_GROUP_ID` environment variables on the builder image. Common builders are as follows:
- heroku/buildpacks: `1000:1000`
- cloudfoundry/cnb: `2000:2000`
- packeto: `2000:2000`
- Dockerfile and Docker Image: Use the user and group id which corresponds to the one running the process within the container.
```shell
dokku ps:restart app-name
```
### Displaying storage reports for an app
@@ -113,7 +141,7 @@ dokku storage:report node-js-app --storage-deploy-mounts
### Sharing storage across deploys
Dokku is powered by Docker containers, which recommends in their [best practices](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#containers-should-be-ephemeral) that containers be treated as ephemeral. In order to manage persistent storage for web applications, like user uploads or large binary assets like images, a directory outside the container should be mounted.
Dokku is powered by Docker containers, which recommends in their [best practices](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#containers-should-be-ephemeral) 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
@@ -139,11 +167,11 @@ You cannot use mounted volumes during the build phase of a Dockerfile deploy. Th
> Note: **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.
## Application User and Persistent Storage file ownership (buildpack apps only)
## App User and Persistent Storage file ownership (buildpack apps only)
> New as of 0.7.1
By default, Dokku will execute your buildpack application processes as the `herokuishuser` user. You may override this by setting the `DOKKU_APP_USER` config variable.
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.