Docker Engine Upgrade, Pinning and Removal
How to see which versions exist, upgrade safely, pin a version so an unrelated apt upgrade cannot move it, roll back, and remove Docker without destroying the volumes that hold your data.
Getting Started Guide 4 of 46 Beginner
- OSUbuntu 26.04 LTS (resolute)
- Docker Engine29.7.2
- Docker Compose5.4.0
- Architectureamd64
- TimeAbout 12 min
- Reviewed20 August 2026
Tested on the versions above. Version numbers change constantly. The uninstall step is deliberately NOT executed here - the commands are shown with their consequences described, because running them would destroy the host this guide was written on.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| DOCKER01 | 192.168.0.21 | Ubuntu 26.04 LTS | Docker Host | 2 Core | 4 GB | 50 GB |
Before you start
- Docker installed from the official apt repository - guide 1 in this path.
- sudo on the host.
-
Know what you are running
Two numbers matter and they can differ. The client is the
dockerCLI; the server is the daemon. A client newer than the server is normal and usually fine, and Compose is a separate plugin with its own version entirely.bash docker version --format "Client {{.Client.Version}} / Server {{.Server.Version}}"Client 29.7.2 / Server 29.7.2docker compose version --short5.4.0Expected resultClient and server versions, and the Compose plugin version separately.
Success conditionYou can state all three. Compose is versioned independently, so it does not follow the Engine number.
-
See which versions the repository actually offers
apt-cache madisonlists every version available from the configured repositories, newest first. This is the list you can upgrade or roll back to - anything not shown here is not installable without adding another source. Note the full version string: it is what you pass to apt when pinning.bash apt-cache madison docker-ce | head -3 docker-ce | 5:29.7.2-1~ubuntu.26.04~resolute | https://download.docker.com/linux/ubuntu resolute/stable amd64 Packages docker-ce | 5:29.7.1-1~ubuntu.26.04~resolute | https://download.docker.com/linux/ubuntu resolute/stable amd64 Packages docker-ce | 5:29.7.0-1~ubuntu.26.04~resolute | https://download.docker.com/linux/ubuntu resolute/stable amd64 PackagesExpected resultSeveral versions, newest first, with the exact strings apt understands.
Success conditionYou have the version list.
apt-cache policy docker-ceshows which one is installed and which is the candidate for upgrade. -
Upgrade
Upgrading is an ordinary package operation, but it restarts the daemon - which stops every running container unless live-restore is enabled. Plan it like any other service restart rather than running it casually mid-afternoon.
bash # this restarts dockerd and will stop running containerssudo apt-get updatesudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin# upgrade all five packages together - mismatched CLI and daemon versions cause odd failuresExpected resultThe five Docker packages upgraded together.
Success condition
docker versionreports the new server version. Upgrade the whole set: a new CLI against an old daemon is a common source of confusing errors. -
Pin a version so nothing moves it
apt-mark holdstops a package being upgraded by anything, including an unattendedapt upgradethat was aiming at something else entirely. This is how you keep a validated Docker version stable on a production host between planned maintenance windows.bash sudo apt-mark hold docker-ce docker-ce-cli containerd.iodocker-ce set on hold.docker-ce-cli set on hold.containerd.io set on hold.apt-mark showholdcontainerd.iodocker-cedocker-ce-cliExpected resultThree packages held, and listed by showhold.
Verify it worked
bash Example session sudo apt-mark unhold docker-ce docker-ce-cli containerd.ioCanceled hold on docker-ce.apt-mark showhold# empty - nothing is pinnedSuccess conditionThe holds are visible. Anyone wondering why Docker will not upgrade should check
apt-mark showholdfirst - a forgotten hold is a common cause. -
Roll back to a previous version
Rolling back is installing an older version explicitly, using the exact string from madison. Two cautions: apt will normally want to upgrade it again on the next run, so pin it immediately afterwards, and a downgrade across a major version can leave state the older daemon does not understand.
bash # downgrading restarts the daemon, and across major versions may not be supportedsudo apt-get install -y --allow-downgrades docker-ce=5:29.7.1-1~ubuntu.26.04~resolute docker-ce-cli=5:29.7.1-1~ubuntu.26.04~resolutesudo apt-mark hold docker-ce docker-ce-cli# pin straight away or the next apt upgrade undoes the rollbackExpected resultThe named version installed, then held.
Success conditionRoll back and pin as one operation. Rolling back without pinning is a change that reverses itself.
-
Uninstall without destroying your data
This is the part that catches people. Removing the packages leaves
/var/lib/dockeralone, so images, containers and - critically - named volumes survive. Deleting that directory is a separate, deliberate act. If you are rebuilding a host and intend to keep the data, remove the packages and stop.bash # 1. remove the packages. /var/lib/docker is NOT touched - images,# containers and named volumes all survive this.sudo apt-get purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin# 2. ONLY if you also want the data gone. This deletes every image,# container and VOLUME on the host, and nothing undoes it.sudo rm -rf /var/lib/docker /var/lib/containerd# back up any named volume you care about first - see the backup guide.Expected resultNo output is shown for either command, because neither was run. This guide was captured on a working Docker host and uninstalling it would have destroyed the environment every other guide in the path was verified on.
Success conditionYou can separate the two acts. Purging packages is recoverable by reinstalling; removing /var/lib/docker is not recoverable at all. Back up first - see guide 13.
-
Check what would be lost before removing anything
Before an uninstall, list the volumes. Anything here is data that the second step would delete permanently, and a volume with no obvious owner is exactly the one somebody will miss.
bash docker volume lsdocker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"# back up anything listed - see the volume backup guide in this pathExpected resultA complete inventory of what removal would destroy.
Success conditionYou have checked before acting. On a host with no volumes this is a formality; on one with a database volume it is the difference between a rebuild and an incident.
Troubleshooting
apt says docker-ce is already the newest version but a newer one exists
Why: The package is held, or the repository list is stale.
Fix:Check for holds first, then refresh the package lists.
bash apt-mark showholdsudo apt-get update && apt-cache policy docker-ceContainers stopped during an upgrade
Why: Upgrading restarts the daemon, and without live-restore that stops every container.
Fix:Enable live-restore in daemon.json before the upgrade window, or accept the downtime and schedule it. Note live-restore does not apply to swarm-managed containers.
bash docker info --format "{{.LiveRestoreEnabled}}"The CLI works but reports an API version mismatch
Why: The client was upgraded without the daemon, or vice versa.
Fix:Upgrade all the Docker packages together. Check both numbers.
bash docker version --format "client {{.Client.APIVersion}} server {{.Server.APIVersion}}"Docker was reinstalled and all the containers are gone
Why:
/var/lib/dockerwas removed, or the package was purged with a tool that cleans data directories.Fix:Nothing recovers this without a backup. Purge packages and delete the data directory as two conscious, separate steps.
bash ls /var/lib/docker 2>/dev/null || echo "data directory is gone"