If you run more than a handful of Docker containers, the command line starts to feel cramped. Portainer gives you a clean web dashboard for everything Docker: containers, images, networks, volumes, and Compose stacks, all manageable with clicks instead of memorized flags. In this guide you will install Portainer CE on Ubuntu 24.04, expose it securely over HTTPS, and deploy your first stack — in about 10 minutes.

Why Portainer instead of just the Docker CLI?

The Docker CLI is powerful, but it assumes you remember every flag and container ID. Portainer earns its place when:

  • You manage many containers across several servers and want one screen instead of ten SSH sessions.
  • Non-terminal users (a teammate, a client) need to restart a service or read logs without learning Docker commands.
  • You deploy Compose stacks often — pasting a YAML file into the web editor and hitting "Deploy" is faster than scp-ing files around and running docker compose up manually.
  • You want visibility: live CPU/memory graphs per container, log tails, and image vulnerability overviews, all without extra tooling.

Portainer CE is free and open source; the paid Business Edition adds SSO, registries governance, and advanced RBAC — none of which a small team needs to get started.

Prerequisites

  • An Ubuntu 22.04 or 24.04 server (a VPS or local VM) with sudo access
  • Docker Engine installed (Step 1 below covers it if you do not have it)
  • Ports 9443 (Portainer HTTPS UI) and 8000 (Edge agent) reachable on your server

Step 1 — Install Docker Engine (skip if already installed)

Portainer itself runs as a Docker container, so Docker has to exist first. Check with:

docker --version

If that errors out, install Docker from the official repository:

sudo apt update && sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

This adds Docker's official APT repo (the keyring step keeps package signatures verifiable), then installs the engine, CLI, containerd runtime, and the Compose plugin. Start and enable the daemon:

sudo systemctl enable --now docker
docker --version

You should see something like Docker version 27.x.x.

Step 2 — Create a persistent data volume

Portainer stores all its data (users, settings, stack definitions) in a Docker volume. Creating it first keeps your dashboard data safe across container recreations:

docker volume create portainer_data

This creates a named volume called portainer_data. Even if you delete and re-run the Portainer container later (for example to upgrade), mounting this same volume restores everything.

Step 3 — Run the Portainer container

Now launch Portainer CE (Community Edition — free) as a long-running container:

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

What each flag does:

  • -d runs the container in the background.
  • -p 9443:9443 exposes the HTTPS web UI on port 9443.
  • -p 8000:8000 exposes the Edge agent tunnel port (used when managing remote hosts).
  • --restart=always brings Portainer back up automatically after a server reboot.
  • -v /var/run/docker.sock:/var/run/docker.sock gives Portainer access to your local Docker daemon — this is how it lists and controls containers.
  • portainer/portainer-ce:lts is the official Long-Term-Support image tag.

Verify the container is healthy:

docker ps --filter name=portainer

The STATUS column should show Up.

Step 4 — Open the firewall

If you use UFW, allow the two Portainer ports:

sudo ufw allow 9443/tcp
sudo ufw allow 8000/tcp
sudo ufw status

If your server sits behind a cloud security group (AWS, DigitalOcean, etc.), allow inbound TCP on 9443 (and 8000) there too.

Step 5 — Create the admin account

Open https://YOUR_SERVER_IP:9443 in a browser. You will see a certificate warning — this is expected, because Portainer generates a self-signed certificate on first start. In Chrome click "Advanced" then "Proceed", or the equivalent in your browser.

Portainer shows a "Create the first administrator user" screen. Important: this screen is only available for the first 5 minutes after the container starts. Pick a strong password and create the admin user. If the timeout already passed and the screen is gone, simply restart the container and reload the page:

docker restart portainer

This restarts the 5-minute window without losing anything.

Step 6 — Connect to your local Docker environment

After logging in, Portainer asks which environment to manage. Choose "Get Started" — this connects to the local Docker daemon on the same server via the socket you mounted in Step 3. No agent installation is needed for the local host.

You land on the Home page showing one environment ("local") with live counts of containers, images, volumes, and networks. Click it to open the dashboard.

Step 7 — Tour the dashboard and deploy a test stack

Click through the left sidebar to see what Portainer manages:

  • Containers — start, stop, restart, inspect, open a console, and tail logs of every container. The stats view shows live CPU, memory, and network graphs.
  • Images — pull from Docker Hub or private registries, retag, and prune unused images to reclaim disk space.
  • Networks & Volumes — create and inspect Docker networks and named volumes without touching docker network or docker volume.
  • Stacks — deploy and manage full Compose applications. Editing a stack's YAML in the web editor and redeploying takes seconds.
  • Registries — connect Docker Hub, GitHub Container Registry, or a private registry once, then pull images through the UI.

Try deploying a stack: go to Stacks → Add stack, name it hello-nginx, choose the Web editor method, and paste this Compose file:

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    restart: unless-stopped

Click Deploy the stack. Portainer pulls the image and starts the container. Now confirm it from the terminal:

curl -s -o /dev/null -w "%{http_code}" http://localhost:8080

A 200 response means your Portainer-managed stack is serving traffic. You can watch its logs and resource stats live under Containers → hello-nginx_web-1.

Next steps: manage remote hosts with the Portainer Agent

One Portainer instance can manage many Docker hosts. On each remote server, run the Portainer Agent container:

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

Then in Portainer go to Environments → Add environment → Docker Standalone → Agent, enter the remote host's IP with port 9001, and give it a name. The remote host appears alongside "local" on the Home page, and you manage its containers exactly the same way. For Docker Swarm or Kubernetes clusters, Portainer supports those environment types too — one dashboard for the whole fleet.

Verify it worked

  • docker ps shows portainer (and hello-nginx_web-1) as Up.
  • https://YOUR_SERVER_IP:9443 loads the Portainer login/dashboard.
  • The Home page shows live container/image/network counts, and the stack list contains hello-nginx.

Common issues & fixes

1. "Your session has expired" / no admin-creation screen.
The 5-minute admin setup window passed. Fix: docker restart portainer, then reload the page within 5 minutes.

2. Port 9443 connection refused.
Either the container is not running (docker ps -a to check, docker start portainer to start) or a firewall/security group is blocking the port. Re-run the UFW commands from Step 4.

3. Browser warns about the certificate.
Normal — Portainer uses a self-signed certificate by default. For production, upload your own trusted certificate under Settings → SSL Certificate in the UI.

4. Cannot see containers owned by another user.
The Docker socket is root-owned. Either run Portainer as root (default) or add your shell user to the docker group: sudo usermod -aG docker $USER, then log out and back in.

5. Upgrading Portainer loses nothing?
Correct — as long as you keep the portainer_data volume. Upgrade with: docker stop portainer && docker rm portainer && docker pull portainer/portainer-ce:lts, then re-run the exact docker run command from Step 3.

Conclusion

You now have Portainer CE running on Ubuntu with a persistent data volume, HTTPS access, and your first Compose stack deployed from the web UI. From here you can manage remote Docker hosts with the Portainer Agent, set up user teams, and schedule container updates — all from the same dashboard.

Setting up Docker tooling, reverse proxies, or full server stacks — and would rather have an expert do it? XpertBees handles end-to-end server setup and DevOps for teams of every size.