GitOps for Docker Compose. Like Argo CD, but without Kubernetes.
Point ConOps at a Git repo containing a docker-compose.yaml.
It clones, pulls, deploys, watches for new commits, detects container drift, and self-heals.
One binary. No cluster required.
Quick Start · Features · Usage Guide · Configuration · API
Run ConOps with a single command:
docker run \
--name conops \
-p 8080:8080 \
-e CONOPS_RUNTIME_DIR=/tmp/conops-runtime \
-v /tmp/conops-runtime:/tmp/conops-runtime \
-v conops_data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
anurag1201/conops:latestOpen http://localhost:8080 and click New App.
Note: For production use, we recommended using Docker Compose.
- Git-driven deployments — push to your branch, ConOps handles the rest
- Continuous reconciliation — configurable loop that keeps desired state in sync
- Self-healing — detects missing, exited, or unhealthy containers and recovers
- Docker preflight + fallback toolchain — checks Docker API compatibility before sync
- Web UI — register apps, inspect status, view containers, trigger syncs, read logs
- REST API + CLI — automate everything; nothing in the UI that the API can't do
- Private repo support — GitHub deploy keys with AES-GCM encryption at rest
- SQLite or PostgreSQL — SQLite for single-node, Postgres for production
- Single binary — no runtime dependencies beyond Docker and Git
ConOps can be managed in two ways: via the Web Dashboard or the REST API / CLI.
The easiest way to get started. Navigate to http://localhost:8080.
- Dashboard: View all registered applications and their current status (
synced,syncing,pending,error). - New App: Click the button to register a repository. You'll need the Git URL, branch name, and path to the Compose file.
- App Details: Click on any app to see its sync history, container health, and logs.
- Actions: You can manually trigger a sync or delete an app directly from its card.
ConOps is API-first. Every action available in the UI can be performed via the REST API.
The conops-ctl CLI helps you manage applications from your terminal.
Installation:
# Install the latest version to /usr/local/bin
curl -sfL https://raw.githubusercontent.com/anuragxxd/conops/master/install.sh | sudo shOr download pre-built binaries from the Releases page.
Configuration:
Set the controller URL if running remotely (defaults to http://localhost:8080):
export CONOPS_URL="http://conops.example.com:8080"Commands:
# List all apps
./conops-ctl apps list
# Register an app (supports private repos via JSON)
./conops-ctl apps add app.json
# Get detailed status
./conops-ctl apps get <app-id>
# Update configuration (partial updates supported)
./conops-ctl apps update <app-id> --branch feature/login --poll-interval 1m
# Force immediate sync
./conops-ctl apps sync <app-id>You can interact directly with the API using curl.
1. Register an App
curl -X POST http://localhost:8080/api/v1/apps/ \
-H "Content-Type: application/json" \
-d '{
"name": "Example App",
"repo_url": "https://github.com/docker/awesome-compose",
"repo_auth_method": "public",
"branch": "master",
"compose_path": "fastapi/compose.yaml",
"poll_interval": "30s"
}'2. List Apps
curl http://localhost:8080/api/v1/apps/3. Get App Details
curl http://localhost:8080/api/v1/apps/{id}4. Force Sync
curl -X POST http://localhost:8080/api/v1/apps/{id}/sync5. Update App
curl -X PATCH http://localhost:8080/api/v1/apps/{id} \
-H "Content-Type: application/json" \
-d '{ "poll_interval": "1m" }'6. Delete App
curl -X DELETE http://localhost:8080/api/v1/apps/{id}All configuration is via environment variables.
| Variable | Default | Description |
|---|---|---|
DB_TYPE |
sqlite |
Storage backend: sqlite or postgres |
DB_CONNECTION_STRING |
— | Required when using postgres |
CONOPS_RECONCILE_INTERVAL |
10s |
How often the reconciler runs |
CONOPS_SYNC_TIMEOUT |
5m |
Max duration for a single sync operation |
CONOPS_RETRY_ERRORS |
false |
Auto-retry apps that entered error status |
CONOPS_RUNTIME_DIR |
./.conops-runtime |
Runtime checkout directory used for compose execution |
CONOPS_TOOLS_DIR |
./.conops-tools |
Cache directory for managed Docker CLI and Compose plugin downloads |
CONOPS_ENCRYPTION_KEY |
— | 32-byte key (raw or base64) for deploy key encryption |
CONOPS_ENCRYPTION_KEY_FILE |
/data/conops-encryption.key |
Path to read/write the encryption key |
For production, we recommend running ConOps with Docker Compose to handle persistence and networking cleanly.
services:
conops:
image: anurag1201/conops:latest
ports:
- "8080:8080"
environment:
- CONOPS_RUNTIME_DIR=/tmp/conops-runtime
- DB_TYPE=sqlite
volumes:
# Persist SQLite DB and encryption keys
- conops_data:/data
# Allow ConOps to manage sibling containers
- /var/run/docker.sock:/var/run/docker.sock
# Runtime directory for checkouts
- /tmp/conops-runtime:/tmp/conops-runtime
volumes:
conops_data:ConOps supports private GitHub/GitLab repositories via SSH deploy keys.
When registering an app via the API, set repo_auth_method to deploy_key and provide the private key:
curl -X POST http://localhost:8080/api/v1/apps/ \
-H "Content-Type: application/json" \
-d '{
"name": "Private App",
"repo_url": "git@github.com:my-org/private-repo.git",
"repo_auth_method": "deploy_key",
"deploy_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----",
"branch": "main",
"compose_path": "docker-compose.yml"
}'Security: Deploy keys are encrypted at rest using AES-GCM. ConOps auto-generates an encryption key on first run, or you can provide your own via
CONOPS_ENCRYPTION_KEY.
┌─────────────┐
│ Git Repo │
└──────┬──────┘
│ poll
┌──────▼──────┐
│ Git Watcher │──── new commit? ──→ mark pending
└─────────────┘
│
┌──────▼──────┐
│ Reconciler │──── clone/fetch → compose pull → compose up
└──────┬──────┘
│
┌──────▼──────┐
│Drift Checker│──── container missing/exited/unhealthy? → requeue
└─────────────┘
Status flow: registered → pending → syncing → synced.
ConOps separates change detection (Git watcher) from state application (reconciler). This keeps the control loop predictable and easy to reason about.
# Run the controller locally
go run ./cmd/conops
# Build the CLI
go build -o bin/conops-ctl ./cmd/conops-ctl
# Run tests
go test ./...MIT — see LICENSE.

