D Darkless Help
Open the portal

Help Running your server Docker and apps

Install Docker and Docker Compose

Install Docker from its official repository, run an app from a compose file, and keep its ports from slipping past your firewall.

4 min Updated 7 Nov 2026 Ubuntu, Debian, AlmaLinux

Docker runs each app in a container with everything it needs, so you don't install its language or libraries yourself. Docker Compose describes an app's containers in one file you can keep and rerun.

Install Docker#

Install it from Docker's own repository. The docker.io and podman-docker packages are older builds without the Compose plugin.

Ubuntu / Debian

Add Docker's signing key and repository. The same lines work on both systems:

sudo apt update && sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release && sudo curl -fsSL "https://download.docker.com/linux/$ID/gpg" -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
. /etc/os-release && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$ID ${UBUNTU_CODENAME:-$VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list

Install Docker and the Compose plugin. It starts straight away, and at every boot:

sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

AlmaLinux / Rocky

Add Docker's repository:

sudo dnf install -y dnf-plugins-core && sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo

Install Docker and the Compose plugin:

sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

If it complains about conflicts with podman or runc, remove those first with sudo dnf remove -y podman runc, then try again.

Start it now and at every boot:

sudo systemctl enable --now docker

Check it works with a tiny test image:

sudo docker run --rm hello-world

Run docker without sudo

To use docker without typing sudo, add your user to the docker group, then log out and back in:

sudo usermod -aG docker alex

Stop logs filling the disk#

Docker keeps every line a container prints, forever, which can fill the disk in weeks. Keep a few small files per container instead:

sudo tee /etc/docker/daemon.json <<'EOF'
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}
EOF
sudo systemctl restart docker

This applies to containers created from now on. Recreate older ones to pick it up: docker compose up -d --force-recreate in their folder.

Run an app with Compose#

The example is Uptime Kuma, which tells you when your websites go down. Every compose file has the same shape. Give each app its own folder under /opt:

sudo mkdir -p /opt/uptime-kuma && cd /opt/uptime-kuma

Write its compose file:

sudo tee compose.yaml <<'EOF'
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    restart: unless-stopped
    ports:
      - "127.0.0.1:3001:3001"
    volumes:
      - ./data:/app/data
EOF
LineWhat it does
imageWhat to run, and which version
restart: unless-stoppedBrings it back after a crash or a reboot
portsPublishes port 3001, on 127.0.0.1 only (see the firewall, below)
volumesKeeps the data in ./data, so it survives the container being replaced

Start it in the background:

sudo docker compose up -d

Then, from the app's folder:

CommandWhat it does
sudo docker compose psShows what's running
sudo docker compose logs -fFollows the log. Ctrl+C stops following, not the app
sudo docker compose restartRestarts the app
sudo docker compose downStops and removes the containers. Data in ./data stays

To reach it from outside with HTTPS, put Caddy in front, with reverse_proxy 127.0.0.1:3001: see Host a website with HTTPS using Caddy.

Update an app

From the app's folder. Your data in ./data stays:

sudo docker compose pull && sudo docker compose up -d

Then clear out old images nothing uses:

sudo docker image prune

Docker and your firewall#

So "8080:80" is reachable from anywhere, whatever ufw status shows. To keep control:

  • Bind to 127.0.0.1, as in the example, and put Caddy in front. The best default.
  • Don't publish what you don't need. Containers in one compose file reach each other by service name, so a database never needs ports.
  • On a VPS, use the portal firewall, which Docker can't change: see Set up the firewall.

Check what's listening. 0.0.0.0 or [::] means from anywhere:

sudo ss -ltnp

Back up your apps#

Back up each app's folder under /opt and you can rebuild it anywhere with docker compose up -d. Dump databases rather than copying their files. See Back up your server.

Still stuck? Open a ticket and say which guide you followed.