Portainer is the control panel Docker never shipped: containers, stacks, images, volumes and logs in a web UI instead of a terminal scroll. I resisted it for a year out of CLI pride and gave in the day I had to explain docker logs -f --tail 200 over the phone. Installing Portainer CE takes about five minutes on any machine that runs Docker, and this guide does it the official way on Ubuntu or Debian, with the two or three decisions that separate a clean install from a confusing one.
Requirements before installing
You need a Linux server with Docker Engine installed and root or docker-group access, and that's the whole list. Any small VPS handles Portainer itself; the app is light and your real resource budget belongs to the containers you'll manage with it. Docker missing? curl -fsSL https://get.docker.com | sh gets you current on Ubuntu 24.04 or Debian 12, or start from our Docker VPS template and skip that step. The commands below are identical on both distros, which is why this one guide covers the ubuntu and debian variants people search separately.
Step 1: Create the data volume
docker volume create portainer_data
Everything Portainer knows (users, environments, stack definitions) lives in this volume. Name it exactly portainer_data unless you enjoy adjusting every maintenance command you'll ever copy from documentation, including the password-reset one you'll want someday.
Step 2: Run the Portainer CE container
The official install command, straight from the Portainer CE docs:
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
Three lines deserve translation. The docker.sock mount is how Portainer sees and controls your Docker engine; forget it and you'll meet the environment errors covered in our local environment fix. The :lts tag pins you to the long-term support line (the 2.33 series as I write this), which is the right home for a server you want boring; the alternative tags chase newer features and newer bugs. And --restart=always means Portainer outlives reboots, an option people notice missing only after the first kernel update.
Port-wise, 9443 serves the UI over HTTPS and 8000 exists for Edge agents you probably don't use yet; the full map, including the legacy 9000 question, is the Portainer ports guide.
Step 3: Create the admin account inside 5 minutes
Open https://YOUR_SERVER_IP:9443, accept the self-signed certificate warning (expected on a fresh install) and create the admin user. Do it promptly: Portainer disables itself if no admin exists within about five minutes of starting, a deliberate security measure against abandoned instances. Miss the window and you'll see the famous "timed out for security purposes" screen; the fix is a simple docker restart portainer, and the details live in our restart guide. Use a real password here, this account can start and stop everything on the machine.
After the account, the setup wizard offers environments to manage. Pick "Get started" for the local Docker engine and you land on the dashboard with your containers listed, Portainer itself among them.
Installing Portainer with Docker Compose instead
Some of us keep every service in compose files as policy, and Portainer plays along. The equivalent docker-compose.yml:
services:
portainer:
image: portainer/portainer-ce:lts
container_name: portainer
restart: always
ports:
- "8000:8000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
Then docker compose up -d from the file's directory. Functionally identical to the run command; operationally nicer because the config is a file you can version. My take on which to use: compose, for the same reason all infrastructure should be text. There's a small philosophical comedy in managing your container manager through a compose file, and it's the correct comedy.
One thing NOT to do, whichever route you took: don't manage the Portainer container from inside Portainer's own UI. Recreating the thing you're standing on ends sessions in confusing ways. Portainer gets maintained from the terminal, everything else gets maintained from Portainer; that division, plus the update routine, is the whole operational story.
Verify the install
Three quick proofs. docker ps shows the portainer container Up. The dashboard at :9443 lists your local environment with a container count that matches reality. And a test action (open any container's logs from the UI) round-trips through the socket without errors.
From here the interesting work starts, which is deploying things: the Portainer stacks guide covers that properly, and if you'd rather begin with Portainer preinstalled, the Portainer VPS template deploys this whole page in one click alongside the OS.

