Repo: github.com/hrodrig/dcctl · Releases: Releases
CLI to manage Docker Compose stacks per environment using a single YAML config file. You define which manifests belong to each environment; dcctl runs docker compose with exactly those files for up, down, status, logs, and more.
Why dcctl? Onboarding new developers with the full product stack becomes trivial: one config, one command, and the whole stack is up. What used to take weeks of “where’s the compose for X?”, “which env file?” and “how do I run the 12 services?” drops to hours — clone, point dcctl at the config, run dcctl up, and you’re coding.
Documentation: Sequence diagrams (Mermaid) for main flows and terminal demo (recorded with VHS) — see docs/. Examples: examples/ — 10 runnable stacks (counter+Redis, WordPress, API+Postgres+Redis, full-stack, multi-env, Postgres+pgAdmin, Flask+Redis, Nginx+Go, Portainer, Prometheus+Grafana) with ports table and show-ports.
- Go 1.26+ (to build)
- Docker and Docker Compose (to run stacks)
From source (recommended): Clone the repo, then:
go install ./cmd/dcctl
# or with version/commit/date baked in:
make installThis installs the binary to $GOBIN (default $HOME/go/bin). Ensure $GOBIN is on your PATH.
Pre-built binaries: Releases provide binaries (.tar.gz, .zip), .deb, and .rpm packages for Linux, macOS, and Windows (amd64 and arm64).
Homebrew (macOS):
brew install hrodrig/dcctl/dcctlBuild: To build in the current directory (e.g. for development):
go build -o dcctl ./cmd/dcctl
# or with version info:
make build
# Custom install path: GOBIN=~/bin make installPublished image (each release): Multi-arch images (linux/amd64, linux/arm64) are published to GitHub Container Registry as ghcr.io/hrodrig/dcctl. Use a version tag or latest.
docker pull ghcr.io/hrodrig/dcctl:v0.1.5
# or
docker pull ghcr.io/hrodrig/dcctl:latestBuild from source: The repo includes a multi-stage Dockerfile (Go 1.26, Alpine 3.19): build stage compiles the binary with version/commit/build date injected via build args; runtime stage is minimal and runs as non-root. Use make docker-build to build locally with version info.
Image details:
- Runtime base: Alpine 3.19. Only
ca-certificatesfor HTTPS. No shell or extra tools in the runtime image. - User: Runs as non-root user
dcctl(binary in/home/dcctl/dcctl). - Labels: OCI image labels (title, description, source).
Build (from repo root): Use make docker-build so the image gets version, commit, and build date from the VERSION file and git (same as release builds).
Run with your config: dcctl inside the container reads config from ~/.dcctl/dcctl.yml (i.e. /home/dcctl/.dcctl/dcctl.yml). Mount your config directory and the Docker socket so the container can use your manifests and talk to the host Docker daemon:
docker run --rm -it \
-v ~/.dcctl:/home/dcctl/.dcctl \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/hrodrig/dcctl:latest upUse any dcctl command in place of up (down, status, logs, show-ports, etc.). If the host Docker socket is only readable by the docker group, run the container with that group (e.g. --group-add $(stat -c '%g' /var/run/docker.sock) on Linux, or ensure the numeric GID matches). For a project-specific config, mount the project dir and pass --config-file:
docker run --rm -it \
-v /path/to/project:/home/dcctl/project:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/hrodrig/dcctl:latest --config-file=/home/dcctl/project/dcctl.yml up- Create a config file:
mkdir -p ~/.dcctl
dcctl config > ~/.dcctl/dcctl.yml-
Edit
~/.dcctl/dcctl.yml: setdcctl.default_environmentanddcctl.environments.<name>.services(list of manifest names). -
Create compose manifests next to the config:
- Path pattern:
<config_dir>/<environment>/<service>.yml - Example:
~/.dcctl/default/app.ymlfor environmentdefaultand serviceapp. - Or run
dcctl manifeststo write a samplesample-app.yml(rename toapp.ymland addappto services if needed).
- Start services:
dcctl up
dcctl status
dcctl show-ports # see published ports and where to connect
dcctl logs -f
dcctl downTry without a config: run an example with dcctl --config-file=examples/01-counter-redis/dcctl.yml up (see examples/; you must pass --config-file because dcctl does not look in the current directory).
dcctl looks for config in one place only when you don’t pass --config-file: ~/.dcctl/dcctl.yml. It does not look in the current directory.
- Default (only):
~/.dcctl/dcctl.yml - Any other path (e.g. project dir):
dcctl --config-file=/path/to/dcctl.yml(required for per-project configs)
Concept: You define environments (e.g. default, uat, prod, fix — any names you want). You choose which one to use either from the CLI with -e/--environment or by setting default_environment in the config. Inside each environment you list the services (manifest names) that dcctl should run; the actual Compose files live at <config_dir>/<environment>/<service>.yml. So one config file, multiple environments, each with its own set of manifests.
Schema (see dcctl config output):
schema_version: config format versioncommon.compose.project_name: Docker Compose project namecommon.compose.ignore_orphans: whether to remove orphan containerscommon.dcctl.verbose_level: 0=quiet, 1=normal, 2=verbose, 3=debugdcctl.default_environment: environment used when you don’t pass-edcctl.environments: map of environment name → list of service (manifest) names
| Command | Description |
|---|---|
dcctl config |
Print default dcctl.yml template |
dcctl up [service...] |
Start services (optional --health-check) |
dcctl down [service...] |
Stop and remove services |
dcctl restart |
Restart all services |
dcctl status |
Show container status (compose ps) |
dcctl logs [service] |
View logs (-f follow, --tail N) |
dcctl exec <service> <cmd> [args...] |
Run command in container |
dcctl manifests |
Write sample compose file to environment dir |
dcctl image ls [service] |
List images from current environment manifests |
dcctl image pull [service] |
Pull those images (latest) |
dcctl image remove [service] |
Remove those images (with confirmation) |
dcctl show-ports |
List published ports per service (where to connect: browser, API, DB) |
dcctl volumes clean [volume...] |
Remove volumes (interactive or by name, --match regex) |
dcctl version |
Show version (-s short, -o json|yaml|text) |
dcctl completion bash|zsh|fish|powershell |
Shell completion |
Use -e / --environment to select an environment; --config-file to use a different config file; --debug for debug logging.
Local build (version from VERSION file):
make build
# override: make build VERSION=v0.2.0Docker image (local):
make docker-build
# image tagged as dcctl, with version/commit/build date from VERSION and gitRelease (from main, requires goreleaser):
brew install goreleaser # or see goreleaser install docs
git tag v0.1.0
make release- Builds binaries for linux/darwin/windows (amd64, arm64), archives, checksums, .deb/.rpm, Docker image (ghcr.io), and Homebrew tap.
- Create a Homebrew tap repo (e.g.
homebrew-dcctl) and setHOMEBREW_TAP_TOKENin CI forbrew install hrodrig/dcctl/dcctl.
Snapshot (no tag): make snapshot — outputs to dist/.
MIT. See LICENSE.
