Quickstart
- On a device that already runs Docker Engine 24+ with Compose v2 (prepare a device):
curl -fsSL https://simpledockerops.com/install | sudo sh - The agent prints an enrollment code and a QR code. In the portal click + Add device, enter the code, name the device, pick a fleet, Enroll device.
- Applications → + New application: paste your
docker-compose.yml. Its variables are detected; set their defaults, mark secrets, save. - Cut release on the application page: choose a version. Images resolve to digests; the preflight lists platforms.
- Deploy to the device or fleet. Watch it go healthy.
Prepare a device
The agent manages the Docker Engine the device already has. It needs Docker Engine 24 or newer with the Compose v2 plugin, running as the system service docker.service on a systemd Linux. The installer checks all of that before it downloads anything; when something is missing it stops and prints these steps for your distribution. It never installs or upgrades Docker itself, so a device keeps exactly the engine you gave it.
Debian 12 and 13, Raspberry Pi OS (64-bit), Armbian
sudo apt-get update && sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin Ubuntu 22.04 and 24.04
sudo apt-get update && sudo apt-get 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
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin Check, then install the agent
docker version --format '{{.Server.Version}}' # 24 or newer
docker compose version --short # 2 or newer (5.x from Docker's repository today)
systemctl is-active docker # active
curl -fsSL https://simpledockerops.com/install | sudo sh - Distribution packages work when they meet the baseline. Debian 13 (
docker.io26 withdocker-compose2) and Ubuntu 24.04 (docker.iowithdocker-compose-v2) do; Debian 12'sdocker.iois Engine 20 and does not. Docker's repository is the one path that is current on every supported OS. - Snap: Docker installed with
snap, the option Ubuntu Server's installer offers, is refused. Its daemon is notdocker.serviceand its socket and data live under/var/snap. Remove it withsudo snap remove dockerand use the steps above. - Development boxes:
curl -fsSL https://get.docker.com | shinstalls the same packages in one go. Docker does not recommend it for production because it takes whatever version is latest that day; for a fleet, pin the version or bake Docker into your image. - Rootless Docker and Podman are not supported. The agent runs as root against
/var/run/docker.sock, and the portal flags any enrolled device whose engine or Compose falls below the baseline.
Applications and releases
An application is a reusable Compose workload. A release is an immutable snapshot of it: the Compose text, every image pinned to an OCI digest, the platforms each image provides, and the default configuration. Releases never change; you cut a new one.
- Variables in
${VAR}form become release configuration with defaults per application, overrides per fleet and per device. - Values marked secret are stored encrypted and never shown again.
- Preflight blocks a release from deploying to a device whose architecture the images do not provide.
Deployments
A deployment assigns a release to a device or fleet with a strategy:
strategy:
waves: [10, 25, 100] # percent of targets, cumulative
max_parallel: 5
min_healthy_s: 120 # per device before the wave counts
fail_threshold_percent: 10
on_failure: pause # or rollback
deadline_minutes: 240 # offline devices past this are reported, not failed Health is evaluated on the device: every service running, services with a healthcheck reporting healthy, plus optional HTTP or TCP probes defined on the application. Rollback re-deploys the previous release with a single 100 percent wave.
Secrets and registries
- Secrets are scoped to organisation, fleet, device, or application; the most specific wins.
- External registries: Docker Hub, GHCR, and any OCI registry with username and token. Credentials are encrypted and used for digest resolution and device pulls.
- The managed registry at
registry.simpledockerops.comgives every organisation private repositories under its own namespace:docker loginwith your portal account, a registry password you set in the portal, or an API key; pushregistry.simpledockerops.com/<org>/<image>:<tag>; releases resolve digests there and each device pulls with its own credential. Storage per plan, usage on the Registry page.
API
Base URL https://app.simpledockerops.com/api/v1. Send Authorization: Bearer sdko_… with a key from Developers.
# Cut a release from CI, then deploy it to the test fleet
curl -X POST https://app.simpledockerops.com/api/v1/applications/APP_ID/releases \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"version":"1.8.4","notes":"fix mqtt reconnect"}'
curl -X POST https://app.simpledockerops.com/api/v1/deployments \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"release_id":"rel_…","target_type":"fleet","target_id":"flt_test",
"strategy":{"waves":[100],"on_failure":"rollback"}}'
# Watch it
curl https://app.simpledockerops.com/api/v1/deployments/DEP_ID -H "Authorization: Bearer $KEY" Security model
- Each device gets a unique credential at pairing; revocable from the portal. No fleet-wide secrets.
- Outbound TLS only. The agent opens no ports.
- Docker socket access is root-equivalent: deployments are treated as privileged actions and every one is audited with who, what, where, when.
- No remote shell in this release. Commands are limited to restart, logs, diagnostics, and prune.
- Agent updates are signed and roll back automatically on failure.