Here's the entire Portainer update, four commands, safe to run as written if you installed with the standard names:
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
If that looks like deleting Portainer and installing it again, correct, that's exactly what a container update is. The part that makes it safe: your data never lived in the container. Users, environments, stacks and settings sit in the portainer_data volume, the stop-rm-pull-run cycle replaces only the application around them and the login page that comes back is your same Portainer, newer. Compose users get the even shorter version from the file's directory:
docker compose pull && docker compose up -d
Now the judgment that surrounds those commands, because the commands were never the hard part.
LTS or latest, decided once
Portainer publishes two tracks and your image tag picks one. The :lts tag follows the long-term support line (2.33 currently), fed with fixes rather than experiments, and it's where servers that matter belong. The :latest tag tracks short-term releases with the newest features and, historically, the newest regressions; the "failed to find local environment" episode that ran through several short-term versions before the LTS fix is the case study, documented in our local environment error guide. My rule is unoriginal and earned: LTS everywhere, and version-pin (portainer/portainer-ce:2.33.1 style) on machines where even scheduled surprises are unwelcome. Whatever you choose, the update commands don't change, only the tag in them does.
One tag warning from the field: mixing tracks by accident. A server installed as :latest and updated with an :lts pull can effectively downgrade, and Portainer's database migrates forward like most apps, so downgrades range from unsupported to broken. Check what you're running (bottom-left corner of the UI shows the version) before pulling a different tag than you installed with.
Back up the data volume before updating
Portainer updates have been drama-free for me across years of them, and the insurance costs so little I take it anyway: a copy of the data volume while the container is stopped.
docker run --rm -v portainer_data:/data -v $(pwd):/backup alpine \
tar czf /backup/portainer-data-$(date +%F).tar.gz /data
Slot that between the stop and the rm, and the worst possible update outcome becomes a restore instead of a rebuild. Release notes are the other thirty seconds; Portainer's are short and flag breaking changes honestly, and skimming them beats discovering a changed default by surprise.
Updating containers through Portainer (the other meaning)
Half the people searching for portainer updates want the reverse: using Portainer to update the containers it manages. Two built-in routes cover it. For a single container, open it and hit Recreate with the "re-pull image" toggle on; Portainer pulls the newest image for that tag and rebuilds the container with identical settings. For stacks, the stack's editor has an Update the stack action with the same re-pull option, which is the proper route when the app came from a compose definition, as everything in our stacks guide does.
Two honest limits. Re-pulling a :latest-tagged image updates to whatever that tag means today, which is exactly as controlled as it sounds; apps you care about deserve version tags you bump deliberately. And Portainer won't schedule updates for you in CE; people wanting automatic container updates bolt on Watchtower, which works and also means machines updating themselves at 3 AM, a trade I decline for anything with a database. Do the immich-style apps on their own release-notes rhythm and let only the boring stateless stuff auto-update, if anything.
The one container Portainer shouldn't update
Itself. The UI will happily show a Recreate button on the portainer container, and pressing it mid-session is sawing the branch you sit on; sometimes it works, sometimes you get a half-recreated container and an SSH session anyway. Portainer gets updated from the terminal with the commands at the top, everything else gets updated through Portainer.
That split is the entire maintenance model, and it's also why the install guide nags about keeping the standard container and volume names: every maintenance command on this page assumed them and worked unmodified.
Verify the update
Log back in at :9443 and read the version in the bottom-left corner; it should say the new number. Environments, stacks and users all present (they will be, the volume never moved). If the login page never comes back, docker logs portainer tells you why in the first screen, and the classic cause is a typo in the recreated run command rather than the update itself, which is one more quiet argument for the compose file that can't be mistyped twice.

