Illustration for Getting started with Docker and Portainer

Getting started with Docker and Portainer

Written by

in

,

Almost everything on my home server, including this blog, my photos (Immich) and my password manager, runs in Docker. Docker is the foundation, and Portainer is the dashboard I use to keep an eye on it all. Here’s how to set both up.

What is Docker?

Docker runs applications in containers. A container bundles an app with everything it needs (libraries, runtime, config) so it runs the same way on any machine, isolated from everything else on the server.

Diagram: one server runs Linux, with Docker Engine on top, which runs isolated containers for Immich, Vaultwarden, Nextcloud, Plex, WordPress and Portainer.
Each app runs in its own container on the same Docker Engine.

Why that matters for a home server:

  • No dependency hell: one app needing PHP 8.3 and another needing an older version doesn’t matter, because each brings its own.
  • Easy to try things: spin an app up, and if you don’t like it, delete the container and it’s gone without leaving any mess behind.
  • Everything is a text file: with Docker Compose, each app is described in one compose.yaml, so rebuilding a server is mostly copying folders back.

Part 1: Installing Docker

These steps are for Ubuntu or Debian. Docker’s official install docs cover other distros.

1. Install Docker Engine and Compose

Docker’s convenience script adds their official repository and installs the engine plus the Compose plugin in one go:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

Prefer not to pipe scripts from the internet? The docs also show the manual apt repository method, which ends up in the same place.

2. Run Docker without sudo

sudo usermod -aG docker $USER
# log out and back in, then:
docker run hello-world
docker compose version

Security If hello-world prints its welcome message, Docker is working. One caution: membership of the docker group is effectively root access to the machine, so only add accounts you trust.

3. Pick a home for your stacks

I keep one folder per app under /opt/stacks, each with its own compose.yaml and data folders. It makes backups and moves simple:

/opt/stacks/
├── immich/compose.yaml
├── portainer/compose.yaml
├── vaultwarden/compose.yaml
└── wordpress/compose.yaml
sudo mkdir -p /opt/stacks
sudo chown $USER:docker /opt/stacks

What is Portainer?

Portainer is a web dashboard for Docker. It doesn’t replace Docker; it’s a friendly interface on top of the same engine you use from the command line. It runs as a container itself and talks to Docker through the Docker socket.

Diagram: your browser connects to Portainer on port 9443; Portainer talks to the Docker Engine through the Docker socket, which manages all containers.
Portainer controls Docker through the Docker socket.

What I actually use it for:

  • At-a-glance status: which containers are running, stopped or unhealthy.
  • Logs and console: read a container’s logs or open a shell inside it from the browser, which is handy from a laptop or phone.
  • Quick actions: start, stop, restart, or recreate a container with a fresh image.
  • Housekeeping: finding and removing unused images and volumes that slowly eat disk space.
  • Stacks: paste a compose file into the web editor and deploy it, without touching the terminal.

Part 2: Installing Portainer

1. Create the compose file

This is the exact file I run, saved as /opt/stacks/portainer/compose.yaml:

services:
  portainer:
    container_name: portainer
    image: portainer/portainer-ce:lts
    restart: unless-stopped
    ports:
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

volumes:
  portainer_data:
    name: portainer_data
  • portainer-ce:lts is the free Community Edition, on the long-term-support release for fewer surprises.
  • 9443 is Portainer’s HTTPS web interface.
  • The docker.sock mount is what lets Portainer control Docker.
  • portainer_data stores Portainer’s own settings and users.

2. Start it

cd /opt/stacks/portainer
docker compose up -d

3. Create your admin account (quickly!)

Browse to https://<your-server-ip>:9443. Your browser will warn about the certificate, because Portainer uses a self-signed one, so accept it and continue. Create the admin user straight away: for security, Portainer locks the setup screen if no admin is created within a few minutes. If that happens, run docker restart portainer and try again.

4. Connect the local environment

Choose Get Started to use the local Docker environment. You’ll see every container on the machine, including ones you started from the command line. Stacks deployed with docker compose show up too. Portainer marks them as created outside Portainer, with limited control, which suits me fine: I keep the compose files in /opt/stacks as the source of truth and use Portainer for monitoring, logs and restarts.

A word on security

Security Anything with access to docker.sock can control every container, and through them the whole host. So I don’t expose Portainer to the internet, even though everything else goes through my reverse proxy. It’s only reachable on my home network (or over a VPN when I’m away). Use a strong password, and turn on two-factor authentication if you’re on a Portainer edition that supports it.

What next?

With Docker and Portainer running, you’re ready to self-host just about anything. A great first project is replacing Google Photos with Immich.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *