Install Containly
Install Containly with Docker Compose or docker run, create the first admin with the setup token and put it behind a reverse proxy.
Containly runs as one container on a Linux host with Docker Engine and Docker Compose v2. The image is published as amslertec/containly for linux/amd64 and linux/arm64, so a mini PC, a virtual machine, a VPS or a Raspberry Pi 4 or 5 with a 64-bit system all work. It listens on port 8420.
Containly talks to the Docker socket, which is equivalent to root on the host. Treat access to it like SSH access and read the security notes before you make it reachable from the internet.
Download the example files
Create a folder and download the example Compose file and the example environment file straight to their final names:
mkdir containly && cd containly
curl -fsSL https://raw.githubusercontent.com/amslertec/containly/main/docker-compose.example.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/amslertec/containly/main/.env.example -o .env
All app settings live in .env; the Compose file loads it with env_file.
Check two settings
- In
.env, keepCONTAINLY_SECURE_COOKIES=falseas long as you open Containly over plain HTTP, for examplehttp://<server-ip>:8420. Set it totrueonly behind HTTPS. Withtrueover plain HTTP the page stays blank or black. - In
docker-compose.yml, replace/path/to/your/compose-projectson both sides of the volume line with the folder that holds your Compose projects. The path inside the container must be the same as on the host, so the stack paths resolve.
The other values in .env can stay as they are: PORT=8420, CONTAINLY_TRUST_PROXY=true, LOG_LEVEL=info. The session secret is created on the first start and kept in the data volume.
Start with Docker Compose
docker compose pull
docker compose up -d
docker compose logs -f containly
The data lives in two named volumes: containly-data (database, session secret, master key) and containly-stacks (stacks created in Containly). They survive updates and re-creates.
Or start with docker run
If you prefer a single command, this is the same setup as the example Compose file (run it in the folder with your .env):
docker run -d --name containly --restart unless-stopped \
--security-opt no-new-privileges:true --cap-drop ALL \
--env-file .env \
-v containly-data:/data \
-v containly-stacks:/stacks \
-v /path/to/your/compose-projects:/path/to/your/compose-projects \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-p 8420:8420 \
amslertec/containly:latest
docker logs -f containly
The Compose file is the documented way; the optional socket proxy below needs it.
Create the first admin
On the first start there is no admin account. Containly runs in setup mode and prints a one-time setup token to the log, inside a boxed banner. The token is also stored in the containly-data volume as /data/setup.token.
- Open
http://<server-ip>:8420in your browser. The setup form appears as long as no admin exists. - Enter a username and a password (you can reveal it and must confirm it), and paste the setup token.
- Submit. The first admin is created, setup mode closes for good and the token is deleted.
Then turn on two-factor authentication for your account.
Put it behind a reverse proxy
For access from outside your own network, put a reverse proxy with TLS in front of Containly, for example Traefik, Caddy or nginx, and change these settings:
- Bind the port to the host only:
"127.0.0.1:8420:8420"underports:indocker-compose.yml(with docker run:-p 127.0.0.1:8420:8420). - Set
CONTAINLY_SECURE_COOKIES=truein.env. - Keep
CONTAINLY_TRUST_PROXY=true, so Containly reads the forwarded headers. - Optional:
CONTAINLY_PUBLIC_URL=https://containly.example.com. Notification e-mails then link to that address.
CONTAINLY_SECURE_COOKIES=true
CONTAINLY_TRUST_PROXY=true
CONTAINLY_PUBLIC_URL=https://containly.example.com
Restart with docker compose up -d after changing .env.
Optional: filtered socket proxy
For least-privilege access to Docker, the example Compose file contains a filtered socket proxy (profile hardened):
docker compose --profile hardened up -d
Then add a TCP endpoint on socket-proxy:2375 in Containly and remove the direct socket mount from the containly service. That port is only reachable on the internal Compose network; never publish plain port 2375.
Next steps
- Add your other Docker hosts
- Activate a Pro licence if you need more than 2 hosts
- Set up backups