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])
  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]

Seal a file (run inside a service directory):

portmgr E .env

This creates .env.age, adds .env to the local .gitignore, and writes a .migrated marker. Commit the .age file and .migrated; never commit the plaintext.

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.10.1

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.10.1
File Size Uploaded
portmgr-1.10.1.tar.gz 31.6 kB Details

Built distribution (wheel)

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

Total release size: 52.4 kB

Release files / portmgr-1.10.1.tar.gz

Download URL portmgr-1.10.1.tar.gz
Size 31.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f11f60345461a6f293186736727f7168e6320d71040cb0b851b5a3886f2ec2f8
BLAKE2b-256 checksum
How to use checksums
8e3b1062a1fd3279524204c915abc78da29b2ca7af22440edef282c4870d0580
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.10.1-py3-none-any.whl

Download URL portmgr-1.10.1-py3-none-any.whl
Size 20.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6c2b0c233994ed04b235d8a4797e0e50cdec012d6b25515ada0f06d8da28d3b3
BLAKE2b-256 checksum
How to use checksums
b95ecf0f94d876d6ae412ba2550f64c4996dfbedb4b34f0d4f4115e4fc83e4a8
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

This release

1.10.1 This release

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