compman manages Docker or Podman Compose stacks—including execution, service operations, volume and image backup, and S3 or HTTP archive deployment—from one CLI.
Project homepage: https://allbegray.github.io/compman/
This tool is dedicated to the brave, slightly unfortunate souls working in environments where a web GUI is unavailable, the firewall blocks everything useful, heavyweight management software cannot be installed, and somehow only raw Docker commands remain.
If every convenient option has been answered with "not allowed," compman is for you.
- Automatically detects Docker Compose and Podman Compose runtimes
- Uses a profile-based
composeconfiguration with per-profile env vars and secrets - Lists and monitors only the current project's containers with
psandstats - Deploys from an S3 prefix/archive or a public HTTP/HTTPS
.tar.gz/.tgz/.ziparchive - Automatically creates
compman.ymlanddocker-compose.ymlwhen deploying into an empty directory - Creates and restores timestamped backups of volumes and container images
- Korean and English help, plus shell completion
- Supports Windows, Linux, and macOS
- Python 3.10 or later
- Docker Compose or Podman Compose
- For S3 deployments: accessible S3-compatible storage and AWS credentials
- For HTTP deployments: a public archive URL (authenticated URLs are not yet supported)
CI verifies Python 3.10–3.13 on Ubuntu, macOS, and Windows. See the Python version strategy section of REVIEW.md for the Python 3.14 support plan and upgrade decision.
Successful CI for a push to main automatically creates an annotated tag from
the version in pyproject.toml. Every version bump must include the matching
dated section in CHANGELOG.md; existing tags are never moved.
# Windows PowerShell
irm https://raw.githubusercontent.com/allbegray/compman/main/install.ps1 | iex:: Windows CMD
curl -fsSL https://raw.githubusercontent.com/allbegray/compman/main/install.cmd -o %TEMP%\install.cmd && call %TEMP%\install.cmd# Linux / macOS
curl -fsSL https://raw.githubusercontent.com/allbegray/compman/main/install.sh | shOpen a new terminal, then verify the installation.
compman -v # --version also works
compman -h # --help also worksLet uv manage the Python interpreter for compman (it downloads a managed Python, so even a system running an older Python like 3.9 works):
uv tool install --force --managed-python git+https://github.com/allbegray/compman.gitTo install a development version from the repository, run:
uv tool install .Update an installed CLI using uv's stored tool source with:
compman upgradeThis runs uv tool upgrade compman --reinstall --managed-python.
If compman upgrade cannot run because the installation is damaged, reinstall from
the upstream Git source. Keeping that source unpinned lets future uv tool upgrade
commands continue moving to newer releases:
uv tool uninstall compman
uv tool install --force --managed-python git+https://github.com/allbegray/compman.git
compman --versioncd my-project
compman init --scaffold
compman stack up
compman service status
compman stack down --yesRunning compman init without arguments displays an interactive menu with these three modes.
compman init --scaffold # Create compman.yml
compman init --s3 s3://bucket/app.tar.gz --build
compman init --seed -o project -p 18080 # Create a test project
compman init --seed -o project -a # Create a test project and archiveOverwriting existing files requires an explicit --force.
Run this from an empty working directory.
mkdir my-app && cd my-app
compman deploy --path s3://my-bucket/releases/app.tar.gz --build --tag my-app
compman stack upA successful deployment creates this file structure.
my-app/
├── compman.yml
├── docker-compose.yml
└── project/ # Application source downloaded from S3
S3 paths support these two formats.
- Prefix: Recursively downloads objects beneath the path and preserves their directory structure.
- Archive: Safely extracts
.tar.gz,.tgz, or.zip; a single top-level directory is flattened automatically.
Public HTTP and HTTPS URLs support archives only. Query strings are allowed, but the URL path must end in .tar.gz, .tgz, or .zip.
compman deploy --path https://example.com/releases/app.zip --build --tag my-appOnly the deployment target with the same name is replaced; other user files are retained. If the source-replacement step fails, the previous tree is restored. A full transaction covering later scaffold generation and image building is not yet guaranteed.
Put all configuration under the compman key in compman.yml.
For case-by-case examples, see examples/compman-config/ (index in examples/README.md).
compose is required and must be a mapping of profiles. A single profile is
enough for one Compose file:
compman:
name: my-stack
compose:
default:
file: docker-compose.ymlMultiple profiles select a Compose file and environment variables per environment:
compman:
name: my-stack
compose:
base: docker-compose.yml
local: docker-compose.local.yml
dev:
file: docker-compose.dev.yml
env:
DATABASE_URL: dev.db.example.com
LOG_LEVEL: debug
prod:
file: docker-compose.prod.yml
env:
DATABASE_URL: prod.db.example.comThe profile file is optional. When omitted, base is used; if there is no base, docker-compose.yml is used. This lets one Compose file use different environment variables per environment.
compman stack up dev
compman service status --profile dev
compman stack down --profile dev --yescompman:
name: my-stack
deploy: s3://my-bucket/releases/app.tar.gz
folder: compose
dirs:
project: project
backup: backup
volume: volume
compose:
default:
file: docker-compose.ymlfolder: Relative subdirectory containing Compose filesdirs.project: Relative subdirectory for managed deployment sourcedirs.backup: Directory for backup archivesdirs.volume: Directory for transferring volume data to and from the hostdeploy: Default S3 URI or public HTTP archive URL forcompman deployandcompman update
Managed paths cannot escape the directory containing compman.yml. --path overrides the configured deploy value for one invocation only.
Use the top-level secrets key to provide shared secret values. Each entry maps
a name to { arn, key }. Profile env values reference these names with
${secrets:NAME} markers; compman fetches the secret's JSON SecretString and
substitutes the value at key when a compose context is built.
compman:
name: my-stack
compose:
default:
file: docker-compose.yml
secrets:
DB_URL:
arn: arn:aws:secretsmanager:ap-northeast-2:123456789012:secret:db
key: dtx/db/url
DB_PASSWORD:
arn: arn:aws:secretsmanager:ap-northeast-2:123456789012:secret:db
key: dtx/db/password- Secrets are injected only where a profile
envvalue contains a${secrets:NAME}marker; they are never passed to compose as standalone variables. A profilesecretsblock merges over the top-level one (profile wins on a name clash). - The
keynames the JSON key inside the secret (slash keys likedtx/db/urlare supported). - The same ARN is fetched once per command invocation, even when multiple env vars reference it.
- A missing secret, unresolvable region, or invalid secret body fails the command
with a clear error. Use the standard AWS credential and region environment
variables;
compman doctorreports a warning when secrets are configured but credentials or region are missing.
Referencing secrets from a profile env: instead of declaring a
DB_URL/DB_PASSWORD pair in secrets and echoing it in docker-compose.yml,
you can build env values with ${secrets:NAME} markers. NAME must be a name
declared in the secrets block. Partial interpolation is supported, and the
marker can sit next to system-variable references (which are left untouched for
docker compose to resolve):
compman:
name: my-stack
compose:
local: docker-compose.local.yml
dev:
file: docker-compose.dev.yml
env:
DATABASE_URL: postgres://${secrets:DB_USER}:${secrets:DB_PASSWORD}@db.example.com
LOG_LEVEL: ${LOG_LEVEL:-info} # system var, resolved by compose
secrets:
DB_USER:
arn: arn:aws:secretsmanager:ap-northeast-2:123456789012:secret:db
key: dtx/db/user
DB_PASSWORD:
arn: arn:aws:secretsmanager:ap-northeast-2:123456789012:secret:db
key: dtx/db/passwordA marker that references an undeclared name fails the command with a clear error.
Using the injected variables: declaring them is not enough. compman passes
the interpolated profile env values into the docker compose process
environment, so docker-compose.yml must reference them with ${VAR}
interpolation:
# docker-compose.yml
services:
app:
image: my-app
environment:
- DB_URL=${DB_URL} # injected from secrets
- LOG_LEVEL=${LOG_LEVEL:-info} # with a default fallbackcompman init [--scaffold | --s3 URI | --seed]
compman deploy [--path SOURCE_URI] [--build] [--tag TAG]
compman update [PROFILE]
compman doctor [--profile PROFILE] [-c|--config PATH] [--json]
compman status [--profile PROFILE] [-c|--config PATH] [--json]
compman ps [PROFILE] [-a|--all] [-c|--config PATH]
compman stats [PROFILE] [-f|--follow] [-c|--config PATH]
compman upgrade
compman version
compman lang [ko|en]
compman completion [powershell|bash|zsh|fish] --install
compman stack up [PROFILE]
compman stack update [PROFILE]
compman stack down [--profile PROFILE] --yes
compman service start [SERVICE...] [--profile PROFILE]
compman service stop [SERVICE...] [--profile PROFILE]
compman service restart [SERVICE...] [--profile PROFILE]
compman service status [--profile PROFILE]
compman service log [CONTAINER] [-f] [-n 50] [--profile PROFILE]
compman service connect [CONTAINER] [--profile PROFILE]
compman volume backup [-z LEVEL] [--no-stop] [--profile PROFILE]
compman volume restore [TIMESTAMP] [--no-stop] [--profile PROFILE]
compman volume pull [--profile PROFILE]
compman volume push [--profile PROFILE]
compman image backup [-z LEVEL] [--source-image] [--profile PROFILE]
compman image restore [TIMESTAMP] [--profile PROFILE]
compman clear
View all options for a command with compman <command> --help.
update: Whendeployis configured, it downloads the S3 or HTTP source, builds images, and starts the stack. Otherwise, it updates the local Compose project withup -d --build.service log: Displays the last 50 lines by default and streams output with-f.ps: Lists running containers in the selected compman project. Use-ato include stopped containers.stats: Prints one resource-usage snapshot for the selected project's running containers. Use-fto stream continuously.service connect: Falls back toshif connecting withbashfails.volume backup/restore: By default, brings the stack down during the operation and restores it afterward. Use--no-stoponly when you understand the consistency risk.image backup: By default, commits and saves the state of the running container. Use--source-imageto save the original image.volume backupandimage backup: gzip level defaults to 6. Use-z 1for faster backups or-z 9for smaller archives.clear: Runsimage prune -affor the selected runtime, so it can delete unused images outside the current project.
compman doctor
compman doctor --json
compman doctor --config /path/to/compman.yml
compman doctor -c /path/to/compman.yml
compman status
compman status --profile PROFILE
compman status --json
compman status --config /path/to/compman.yml
compman status -c /path/to/compman.ymldoctor checks configuration, Compose files, container-runtime availability and connectivity, managed directories, and AWS credentials. status displays the service state of the running stack. --json outputs structured JSON suitable for automation.
ps and stats are deliberately project-scoped. Use docker ps, docker stats, or the Podman equivalents directly when you need runtime-wide results.
If a required doctor check fails, it returns exit code 1. status returns exit code 1 when the target stack does not exist or status retrieval itself fails. If the stack exists and retrieval succeeds, it returns exit code 0 even if every service is stopped or exited. Missing AWS environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) are non-failing warnings, so doctor returns exit code 0 if all other required checks pass.
Backup files are stored in dirs.backup.
<stack>.volume.<YYYYMMDD_HHMMSS>[_<microseconds>].tar.gz
<stack>.image.<YYYYMMDD_HHMMSS>[_<microseconds>].tar.gz
When restoring without a timestamp, choose an available backup interactively. Volume restore and volume push merge data into the target; they do not delete files that exist only at the target. Image restore loads the image into the runtime but does not automatically change the Compose image tag.
The automatic detection order is:
docker compose → podman compose → podman-compose → docker-compose
To prefer Podman, set an environment variable.
export CONTAINER_RUNTIME=podman
# PowerShell: $env:CONTAINER_RUNTIME="podman"On Windows when Docker is the selected runtime, compman checks Docker Desktop before compman stack up, compman update, compman stack update, and a compman deploy --build image build. If Docker Desktop is not ready in an interactive terminal, it asks:
Docker Desktop is not running. Start it now? [Y/n]
Press Enter (or answer Y) to start Docker Desktop. compman waits up to 60 seconds for it to become ready before continuing. Answering N exits with guidance to start Docker Desktop manually and retry.
In non-interactive execution, compman never starts Docker Desktop; it exits with a concise error instead. This check does not run for Podman, read-only commands, backup/restore, or stop/down paths.
Expected operational failures, including Docker Desktop readiness failures, are printed as concise messages without Python tracebacks.
Uses standard AWS SDK environment variables.
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_DEFAULT_REGION=ap-northeast-2
export AWS_ENDPOINT_URL_S3=http://localhost:4566 # Default Ministack/LocalStack portIf AWS_ENDPOINT_URL_S3 is absent, AWS_ENDPOINT_URL can also be used.
compman lang ko # Set the default language for the current process
compman --lang en --help # Use English for this invocation only
export COMPMAN_LANG=ko # Set the default language in the shell environment
compman completion powershell --install
compman completion bash --install
compman completion zsh --install
compman completion fish --installuv sync --dev
uv run ruff check compman tests
uv run mypy compman
uv run pytest --cov=compman --cov-report=term-missingCI verifies:
- Ubuntu, macOS, and Windows × Python 3.10–3.13 tests
- 100% statement and branch coverage
- Ruff and mypy
- Wheel build, isolated installation, and CLI execution
- Ministack S3 download, Docker image build, and Compose start/stop E2E
For current constraints and the improvement backlog, see REVIEW.md. For test-project usage, see each README under test/.