Skip to main content

portmgr

portmgr is a wrapper around docker-compose that allows running typical docker-compose commands recursively. Additionally, it shortens commands to a single letter.

Let's say you have organized your compose files like this, you just add a dckrsub.yml in each parent folder:

docker/
├── dckrsub.yml
├── reverse-proxy/
│   └── docker-compose.yml
├── storage
│   ├── dckrsub.yml
│   ├── nextcloud/
│   │   └── docker-compose.yml
│   └── immich/
│       └── docker-compose.yml
└── scripts

Each dckrsub.yml has a list of subdirectories, which portmgr should decend into. For example, the dckrsub.yml in docker/ might look like this:

- reverse-proxy
- storage

And the dckrsub.yml in docker/storage/ like this:

- nextcloud
- immich

Now, if you run portmgr u in docker/ it will run docker compose up -d in reverse-proxy/, storage/nextcloud/ and storage/immich/.

portmgr starts from the current directory, so when running it in docker/storage/, it will run docker compose only in nextcloud/ and immich/. You can also use it in a directory with a docker-compose.yml as a shortener for docker-compose commands.

Commands

The following commands are available. The respective docker-compose commands are in brackets.

  u   Create and start containers (up)
  p   Pull images (pull)
  s   Stop services (stop)
  d   Stop and remove containers (down)
  l   Show container logs (logs)
  a   Run shell in container (exec -it <service> sh)
  b   Build images (build)
  c   List containers (ps)
  t   List processes in containers (top)
  r   Build and push to registry (build, push)
  v   Scan container images for vulnerabilities
  E   Encrypt/seal secret file(s) with age (requires portmgr[secrets])
  D   Decrypt/unseal sealed secret files (requires portmgr[secrets])
  S   Show secret migration status (requires portmgr[secrets])
  M   Move literal environment values from the compose file into .env
  R   Rotate postgres/mariadb passwords and write new values to .env

You combine multiple commands. For example portmgr dul, runs docker compose with down, up and logs, thus stopping, removing and starting all containers and then showing the logs.

Installation

sudo pip install portmgr

Or build it from source (here using the latest commit on master branch)

sudo pip install https://github.com/Craeckie/portmgr.git

Sealing secrets

portmgr can encrypt secret-bearing files (.env, config files) with age so they are safe to commit to git. Decryption happens once at setup time; the plaintext files remain on disk for Docker to use normally.

Requires the secrets extra:

pip install portmgr[secrets]

Move secrets out of the compose file first (run inside a service directory, or above it to go through every stack):

portmgr M

Lists each literal environment: value with secret-looking keys (password, token, key, …) preselected, asks which to move, previews the result and asks for confirmation. Each chosen value is appended to .env (created with mode 600 if missing) and replaced in the compose file with "${NAME}"; nothing else in the compose file changes, comments included. NAME is the key itself, or <SERVICE>_<KEY> when that name is already used with another value, is referenced elsewhere in the file, or is set in your shell (which would override .env). Values that already reference a variable, span several lines, use YAML anchors or tags, or that compose would re-type (True, 0o17, 1.50, …; quote them to move them) are left alone with a note. Then seal .env as below and commit the compose file.

Seal a file (run inside a service directory):

portmgr E .env

This creates .env.age and writes a .migrated marker. Commit the .age file and .migrated; never commit the plaintext — E does not touch .gitignore, so make sure .env is ignored yourself.

Decrypt on a new server (run from any ancestor directory):

portmgr D

Recurses via dckrsub.yml and decrypts every *.age whose plaintext is missing. Pass --force to overwrite existing plaintext from the sealed copy.

Check migration progress:

portmgr S

Reports DONE, PENDING, or CLEAN for each service and prints a summary tally. A .migrated marker always means DONE, even if the compose file still contains what looks like a secret — create it by hand for services that need no sealing. CLEAN only means nothing was detected; portmgr u's footer still counts a CLEAN service as unsealed until it has a .migrated.

Rotate database passwords:

portmgr R

Finds postgres and mariadb services in each compose stack, generates a new random password, runs ALTER USER in the running container, and writes the new value(s) to .env. If a password was previously hardcoded in the compose file rather than referenced via ${VAR}, a warning is printed reminding you to update the compose file to use the variable reference.

Passphrase: portmgr prompts once and caches the passphrase for the rest of the run. For non-interactive use (e.g. in scripts or provisioning), set:

PORTMGR_PASSPHRASE=<passphrase> portmgr D

After running portmgr u, a footer line is printed if any services have not yet been sealed.

Tipps

If you use portmgr a lot like me, you might want to shorten it to one letter. For bash, you can add alias p='portmgr' to ~/.bashrc. For fish-shell you can add abbr p portmgr to ~/.config/fish/config.fish.

Release files for portmgr 1.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for portmgr 1.11.0
File Size Uploaded
portmgr-1.11.0.tar.gz 41.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for portmgr 1.11.0
File Interpreter ABI Platform
portmgr-1.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.0 kB

Release files / portmgr-1.11.0.tar.gz

Download URL portmgr-1.11.0.tar.gz
Size 41.5 kB
Tags Source
SHA-256 checksum
How to use checksums
630f55966fb93fa7b3dea17773c2e6e92925d04ec68607d65dbc8b18173e7b5f
BLAKE2b-256 checksum
How to use checksums
ec8156ee3320656062855fd14419362d8cfb26ed2e669d8b5016700f117d4b08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / portmgr-1.11.0-py3-none-any.whl

Download URL portmgr-1.11.0-py3-none-any.whl
Size 27.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4842c43a706f3a2dde879867cd445abc0b221797ef91d56cb8e40cbfe26f5d4c
BLAKE2b-256 checksum
How to use checksums
2f7482e9220e00bd51d103664761e3e89b25d6129cb3125b88b703f95e1f1138
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

1.11.1

2 release files

This release

1.11.0 This release

2 release files

1.10.1

2 release files

1.10.0

2 release files

1.9.2

2 release files

1.9.1

2 release files

1.9.0

2 release files

1.8.3

2 release files

1.8.2

2 release files

1.8.0

2 release files

1.6.4

2 release files

1.6.3

1 release file

1.6.2

1 release file

1.6.1

1 release file

1.6.0

1 release file

1.4.8

2 release files

1.4.7

2 release files

1.4.4

1 release file

1.4.0

1 release file

1.3.6

1 release file

1.3.5

1 release file

1.3.4

1 release file

1.3.3

1 release file

1.3.2

1 release file

1.3.0

1 release file

1.2.2

1 release file

1.2.1

2 release files

1.2.0

1 release file

1.1.2

1 release file

1.1.1

1 release file

1.0.5

1 release file

1.0.3

1 release file

1.0.2

1 release file

1.0.0

1 release file

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page