Upgrade a Docker Plugin Without Losing Its Configuration
You will upgrade an existing Docker Engine plugin while keeping its installed identity and configuration, then confirm that it is enabled again. Allow 10 to 20 minutes, plus time for a maintenance window if containers depend on the plugin. The upgrade is service-disrupting: Docker requires the plugin to be disabled first, so anything using it may stop working during the change.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a Linux host with Docker Engine running, an existing managed plugin, permission to access the Docker daemon, and a tested source image if you intend to move to a particular release. The installed CLI checked for this guide is Docker 29.8.1 from docker-ce-cli package version 5:29.8.1-1~ubuntu.24.04~noble. Command output and the plugin names on your host will differ.
Most commands below need Docker daemon access. Run them as your ordinary account when it belongs to the Docker group. If it does not, prefix the Docker command with sudo, or use your site's approved Docker access method. Do not add yourself to a privileged group as an improvised fix.
Do not start by guessing a plugin name or a remote image. First record what is installed, which containers or volumes rely on it, and how you will re-enable it if the upgrade fails.
1. List the installed plugins
List managed plugins and copy the exact value in the NAME column. The enabled state matters because the upgrade command will not accept an enabled plugin.
$ docker plugin ls
ID NAME DESCRIPTION ENABLED
abc123 example/volume:1.2 Example volume driver true
$ PLUGIN='example/volume:1.2'
$ docker plugin inspect "$PLUGIN"
The inspect output is JSON and can be long. Look for the plugin's settings, references and current image details before choosing a replacement. Save a copy if this is a change-controlled host:
$ docker plugin inspect "$PLUGIN" > "${PLUGIN##*/}-before-upgrade.json"
Checkpoint: you have an exact plugin name, a record of its current state, and a maintenance window. If docker plugin ls is empty, there is no existing managed plugin for this procedure.
2. Check whether a remote image is needed
The remote argument is optional. Without it, Docker re-pulls the current image and uses the updated version available for that image reference. With a remote argument, Docker upgrades to the specified remote plugin image. Use an explicit reference when your release process pins a tag or digest, and verify that it belongs to the plugin you intend to replace.
$ REMOTE='registry.example.invalid/vendor/plugin:2.4.1'
# Review the vendor's release notes and the exact reference before using it.
printf 'plugin: %s\nremote: %s\n' "$PLUGIN" "$REMOTE"
Do not treat a changing tag such as latest as a reproducible release. If the registry or plugin author supplies a digest, use the documented digest form instead. A remote image can request permissions that the current plugin did not need.
3. Disable the plugin
This is the first state-changing command. Disabling can interrupt containers, volume mounts or network operations that use the plugin. Stop or drain dependent workloads according to your service runbook before continuing.
$ docker plugin disable "$PLUGIN"
example/volume:1.2
$ docker plugin ls
ID NAME DESCRIPTION ENABLED
abc123 example/volume:1.2 Example volume driver false
The name and table formatting are illustrative. The useful checkpoint is that the target's ENABLED value is false. If Docker refuses to disable it because it is in use, stop the dependent workload and investigate the dependency rather than forcing the upgrade.
4. Upgrade the disabled plugin
Choose one of these commands. The first refreshes the current image reference. The second supplies a particular remote image.
$ docker plugin upgrade "$PLUGIN"
$ docker plugin upgrade "$PLUGIN" "$REMOTE"
The command may need network access to the registry. It keeps existing references to the plugin working after a successful upgrade, but the plugin remains disabled until you enable it again. A successful command normally returns to the shell without a detailed summary, so check the plugin state rather than relying on the absence of an error.
If Docker reports that the remote plugin does not match the existing plugin image, stop and verify the image name, vendor and intended migration path. The --skip-remote-check option bypasses that comparison:
$ docker plugin upgrade --skip-remote-check "$PLUGIN" "$REMOTE"
Use that option only when you have independently confirmed that the replacement is compatible. It removes a safety check; it does not make two unrelated plugins compatible and it does not preserve a rollback image for you.
5. Grant new permissions only deliberately
A replacement plugin can request host capabilities, devices, mounts or network access. Those permissions are security-sensitive. Review the request against the plugin documentation and your change record before granting it.
$ docker plugin upgrade --grant-all-permissions "$PLUGIN" "$REMOTE"
--grant-all-permissions grants all permissions needed to run the plugin. Do not combine it with an unreviewed image or use it merely to silence a prompt. If the plugin needs only selected permissions, stop and use the narrower approval path offered by the plugin and your Docker version, rather than accepting everything by habit.
6. Re-enable and verify the result
Re-enable the plugin only after the upgrade command succeeds. This is another state-changing operation and can make the plugin available to workloads again.
$ docker plugin enable "$PLUGIN"
example/volume:1.2
$ docker plugin ls
ID NAME DESCRIPTION ENABLED
def456 example/volume:1.2 Example volume driver true
$ docker plugin inspect "$PLUGIN"
The plugin ID can change after an upgrade, so do not use the old ID as proof that nothing changed. Confirm the enabled state, inspect the resulting settings, and exercise a small, non-critical operation supported by the plugin. For a volume plugin, that might mean a test volume in an isolated project; do not test against production data.
Checkpoint: the target is enabled, its configuration is present, and a safe smoke test works. Only now should you return dependent workloads to service.
When the upgrade fails
If the upgrade fails while the plugin is disabled, leave it disabled and preserve the error output. Check registry access, the remote reference, and the plugin's compatibility notes. Do not repeatedly retry with --skip-remote-check or --grant-all-permissions without understanding the failure.
If the old plugin image is still available locally, the practical recovery is to restore the previous plugin through the documented Docker plugin lifecycle for your release, then enable it and run the same smoke test. The exact recovery command depends on whether the upgrade created a new image reference or changed the tag in place, so inspect first:
$ docker plugin ls
$ docker plugin inspect "$PLUGIN"
$ docker info
If a running workload has already been interrupted, restore service using its normal deployment procedure after the plugin is healthy. Do not remove the plugin as a first response: removal is destructive to the installed plugin state and is not an undo for an uncertain upgrade.
Done means
- You recorded the exact plugin name and inspected its pre-upgrade state.
- Dependent workloads were stopped or drained before disabling the plugin.
- You verified the remote image, or deliberately refreshed the current image.
- You used
--skip-remote-checkor--grant-all-permissionsonly with an explicit compatibility and security decision. - The upgraded plugin is enabled and passes a safe smoke test.
- You know which deployment procedure restores dependent workloads if the plugin fails later.