Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

How to Update Portainer: The Container Dance and the Backup You Should Take First

Sean

Platform Writer

Aug 26, 2026
7 min read

Updating Portainer is docker stop, docker rm, docker pull, then docker run with exactly the same volume mount as before. The container is disposable; portainer_data is not. Get the volume argument wrong on the final step and you have a fresh install with none of your environments, users or settings.

How to Update Portainer: The Container Dance and the Backup You Should Take First

Portainer manages containers, which makes updating it slightly recursive — you cannot use it to replace itself while it is running. The procedure is short and the one genuinely destructive mistake is easy to make, so it is worth being deliberate about the volume.

Table of contents

Back up first

Do this before touching anything. Portainer has a built-in backup under Settings, which produces a file containing your environments, users, teams, registries and access rules — everything that is annoying to reconstruct.

Take it, set a password on it, and download it somewhere that is not the machine you are about to change.

A volume-level backup is the more complete option:

docker run --rm \
  -v portainer_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/portainer-backup.tar.gz -C /data .

That produces a tarball of the entire data volume, restorable by reversing the direction:

docker run --rm \
  -v portainer_data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/portainer-backup.tar.gz -C /data

Also note your current version before upgrading — it is in the bottom-left of the UI. If you need to roll back, you need to know which tag to roll back to, and the answer is not obvious once the container is gone.

Confirm the volume you are using

This is the step that prevents the bad outcome. Do not assume it is portainer_data because that is what the documentation says — check:

docker inspect portainer --format '{{json .Mounts}}' | python3 -m json.tool

Or the whole run configuration, which is worth copying somewhere before you delete the container:

docker inspect portainer --format '{{.Config.Image}}'
docker inspect portainer --format '{{range .HostConfig.PortBindings}}{{.}}{{end}}'
docker inspect portainer --format '{{range .Mounts}}{{.Source}}:{{.Destination}} {{end}}'

Write down or paste somewhere:

  • The data volume name or host path.
  • The published ports — 9443 for HTTPS, 9000 for HTTP, 8000 for the Edge agent tunnel.
  • Any TLS certificate paths passed as arguments.
  • The restart policy.

Once you docker rm the container, that configuration is gone. Reconstructing it from memory is how people end up with a working Portainer that has lost its Edge agents.

The update itself

docker stop portainer
docker rm portainer
docker pull portainer/portainer-ce:lts

docker run -d \
  -p 8000:8000 -p 9443:9443 \
  --name=portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:lts

docker rm portainer removes the container, not the volume. Named volumes survive container removal — that is the entire reason for using one. The data is only at risk if you pass -v to docker rm, or use a different volume name on the way back up.

For Business Edition, swap the image for portainer/portainer-ee:lts and keep the same arguments.

If you run Portainer via Compose, it is shorter and safer because the configuration is in a file:

docker compose pull
docker compose up -d

Which is a good argument for moving to Compose the next time you touch this — the run configuration becomes something you can read and version rather than something you must remember.

Prefer the lts tag over latest. LTS releases receive patches without feature churn, and latest will move you across major versions without warning.

Agents, and the order to do things in

If you manage remote hosts, they run a Portainer Agent that must be updated too. The order matters: update the server first, then the agents. Portainer supports a newer server talking to older agents, but not reliably the reverse.

On each remote host, the agent update follows the same shape:

docker stop portainer_agent
docker rm portainer_agent
docker pull portainer/agent:lts

docker run -d \
  -p 9001:9001 \
  --name portainer_agent \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  portainer/agent:lts

For a Swarm deployment, update the agent service in place rather than recreating it:

docker service update --image portainer/agent:lts portainer_agent

Edge agents behave differently — they poll the server rather than being connected to, so they generally reconnect on their own after a server update. If one does not come back, check that port 8000 is still published on the server, since that is the tunnel port and it is easy to omit when reconstructing the run command.

When it does not come back

Check the container is running and read its log first:

docker ps -a | grep portainer
docker logs portainer --tail 50

A fresh setup screen means the data volume is not attached. Stop, confirm the volume name with docker volume ls, and recreate with the correct -v. Do not create an admin account on the empty instance — that writes to the new volume and complicates the recovery.

Port already in use usually means the old container was not fully removed, or something else took the port in the gap:

docker ps -a | grep 9443
ss -tulpn | grep 9443

Version too old to upgrade directly. Portainer 1.x must go via 2.0.0 before anything newer. Jumping straight from 1.x to a current release produces a broken instance, and the fix is to restore the backup and do it in two steps.

Rolling back, which is why you noted the version earlier:

docker stop portainer && docker rm portainer
docker run -d ... portainer/portainer-ce:2.19.4

A rollback across a major version may need the pre-upgrade backup restored as well, because the newer version can migrate the data format in place.

How this fits the rest of the stack

This whole procedure exists because Portainer’s state lives in a volume that is only connected to the container by an argument you retype. That is normal for self-hosted Docker, and it is also the reason routine updates carry a small risk of losing configuration nobody wrote down.

The alternative is having the platform hold that state. RunxBuild runs services from a connected GitHub repository with environment variables, persistent storage and deploy history managed per service, and rollback to a previous deploy as a selection rather than a retyped docker run — so updating does not depend on remembering the arguments. The RunxBuild hosting calculator shows what a service with storage and a managed database costs together.

Useful related references:

FAQ

Does updating Portainer delete my settings?

Not if the new container mounts the same named volume. docker rm removes the container but leaves named volumes intact. Data is only lost if you use a different volume name when recreating, or pass -v to docker rm. Confirm the volume with docker inspect before you remove anything.

Can I update Portainer from inside Portainer?

The UI offers an update notification with an Update now button, which works for standard installations. For anything unusual — custom TLS certificates, non-standard ports, Swarm deployments — the manual stop, remove, pull, run sequence is more predictable.

Should I use the lts or latest tag?

lts — it receives patches without feature churn, and it will not move you across a major version unexpectedly. latest tracks the newest release including breaking changes, which is rarely what you want for infrastructure you rely on.

Do I need to update Portainer agents too?

Yes, and update the server first. A newer server works with older agents, but an older server with newer agents is not reliably supported. On Swarm, use docker service update --image portainer/agent:lts portainer_agent rather than recreating the service.

Portainer shows the setup screen after updating. What happened?

The data volume is not attached, so it started empty. Do not create an admin account — that writes to the wrong volume. Stop the container, check docker volume ls for your data volume, and recreate with the correct -v portainer_data:/data argument.

#how to update portainer#portainer#docker#containers#self-hosting