| name | docker-compose-ui |
| description | Operate and troubleshoot the docker-compose-ui dashboard -- project discovery, container actions, log streaming, audit log, and deployment. |
| triggers | ["docker-compose-ui","compose ui","compose dashboard"] |
When to use this skill
Use this skill when working on or using docker-compose-ui: configuring the dashboard, running container actions from the UI, debugging project discovery, reviewing the audit log, or deploying the stack.
Prerequisites
- Docker Engine running and socket accessible at
/var/run/docker.sock (or DOCKER_HOST)
- Compose projects organized as subdirectories under
COMPOSE_DIR
- Each project subdirectory must contain
docker-compose.yml or docker-compose.yaml
- Containers started with
docker compose up carry the required com.docker.compose.project label automatically
Quick Start (development)
git clone <repo> docker-compose-ui
cd docker-compose-ui
pnpm install
cp .env.example .env
cd backend && pnpm dev
cd frontend && pnpm dev
Quick Start (Docker)
cp .env.example .env
docker compose up -d
Environment Variables
| Variable | Default | Description |
|---|
PORT | 3000 | Express server port |
DOCKER_SOCKET | /var/run/docker.sock | Docker Unix socket path |
DOCKER_HOST | `` | TCP Docker host, overrides socket (e.g. tcp://docker:2376) |
COMPOSE_DIR | ./projects | Directory containing Compose project subdirectories |
DB_PATH | ./data/audit.db | SQLite audit log database path |
CORS_ORIGIN | http://localhost:5173 | Allowed CORS origin for the dashboard |
VITE_API_URL | http://localhost:3000 | API base URL used by the frontend |
Project Discovery
The backend scans COMPOSE_DIR on each request to GET /api/projects:
- List all entries in
COMPOSE_DIR.
- For each subdirectory, check for
docker-compose.yml or docker-compose.yaml.
- Parse the YAML with
js-yaml to extract service names.
- Query Docker for all containers with label
com.docker.compose.project.
- Match containers to projects by the label value.
- Services listed in the compose file but with no container are shown as
not_created.
A project appears in the dashboard even if all its containers are stopped, as long as a compose file exists on disk.
Container Actions
All actions go through the REST API and are logged to the audit log.
| Action | Endpoint | Scope |
|---|
| Start service | POST /api/projects/:project/services/:service/start | Single container |
| Stop service | POST /api/projects/:project/services/:service/stop | Single container |
| Restart service | POST /api/projects/:project/services/:service/restart | Single container |
| Compose Up | POST /api/projects/:project/up | All services (spawns subprocess) |
| Compose Down | POST /api/projects/:project/down | All services (spawns subprocess) |
| Pull images | POST /api/projects/:project/pull | All images (spawns subprocess) |
up, down, and pull spawn docker compose as a subprocess in the project directory and stream output back to the caller.
Log Streaming
Logs are streamed via Server-Sent Events (SSE):
GET /api/projects/:project/services/:service/logs
Each event:
event: log
data: {"timestamp":"2024-03-15T11:04:32Z","stream":"stdout","line":"INFO Server started"}
The backend uses dockerode with follow: true and tail: 200. On client disconnect, the Docker log stream is destroyed immediately to prevent resource leaks.
Resource Stats
One-shot stats endpoint (not streaming):
GET /api/projects/:project/services/:service/stats
Response:
{ "cpuPercent": 3.2, "memoryMb": 186 }
The frontend polls this endpoint every 5 seconds for each visible service.
Audit Log
Every container action writes a row to audit_log in SQLite. View the last 100 entries:
GET /api/audit
Audit entries include: timestamp, project, service (null for project-level actions), action, result (success or error), and error_message.
Settings
GET /api/settings -- read current settings
POST /api/settings -- update refresh interval
COMPOSE_DIR and DOCKER_SOCKET are read-only (from environment). The refresh interval is stored server-side and returned on GET /api/settings. The frontend also stores its own UI preferences in localStorage.
API Reference
| Method | Path | Description |
|---|
GET | /api/health | { ok: true } |
GET | /api/projects | All discovered projects |
GET | /api/projects/:project | Project detail with all services |
GET | /api/projects/:project/services/:service | Single service detail |
POST | /api/projects/:project/services/:service/start | Start container |
POST | /api/projects/:project/services/:service/stop | Stop container |
POST | /api/projects/:project/services/:service/restart | Restart container |
POST | /api/projects/:project/pull | Pull all images |
POST | /api/projects/:project/up | Compose up |
POST | /api/projects/:project/down | Compose down |
GET | /api/projects/:project/services/:service/logs | SSE log stream |
GET | /api/projects/:project/services/:service/stats | CPU and memory |
GET | /api/audit | Recent audit entries |
GET | /api/settings | Current settings |
POST | /api/settings | Update settings |
Troubleshooting
"Cannot connect to Docker Engine"
- Confirm Docker is running:
docker info
- Check socket permissions:
ls -la /var/run/docker.sock
- If running in Docker, verify the socket is mounted with
-v /var/run/docker.sock:/var/run/docker.sock
- For Docker Desktop on macOS: the socket may be at
~/.docker/run/docker.sock
"No projects found"
- Verify
COMPOSE_DIR points to a directory containing project subdirectories
- Each subdirectory must have a
docker-compose.yml or docker-compose.yaml file
- Run
docker compose up -d in at least one project directory to create containers
Project shows but services are all "not_created"
- The compose file was parsed but Docker found no containers with a matching
com.docker.compose.project label
- Run
docker compose up -d in that project directory
SSE logs disconnect immediately
- Ensure no proxy (nginx, Caddy) is buffering the response; set
X-Accel-Buffering: no
- Check that the container is running; logs cannot be streamed from a stopped container
Compose Up / Down shows no output
- The subprocess requires
docker compose (v2) to be installed and on PATH in the backend container
- Verify with
docker compose version