Easy Docker Manager
Easy Docker Manager (EDM) lets you inspect Docker containers from a keyboard-driven terminal interface. It uses Urwid for the screen and the Docker Python SDK to read container data.
With EDM, you can view:
- running containers, with an option to include stopped containers
- recent logs with automatic updates
- container environment variables
- a readable summary of Docker inspection data
- current CPU, memory, network, disk, and process statistics
- the process list returned by Docker top
- Start, Stop, and Restart container actions
- live filtering, grouping, and sorting of the container list
- a separate search query for each container tab
- export of the active tab to a local text file
- a local JSON configuration file
Demo
Requirements
- Python 3.9 or newer
- Docker installed and running
- permission to access the Docker daemon you want to use
- a terminal window of at least 120 columns by 30 rows
EDM supports local Docker sockets, Windows named pipes, SSH contexts, and TCP contexts secured with verified TLS. Plain TCP connections and contexts that skip server verification are listed but cannot be selected.
Installation
For normal use, install EDM with pipx:
pipx install easy-docker-manager
pipx keeps EDM in its own environment and makes the edm command available
from your terminal.
You can also install EDM with pip. Using a virtual environment keeps it
separate from other Python packages:
python -m venv .venv
Activate the environment on Linux or macOS:
source .venv/bin/activate
Activate it in Windows PowerShell:
.venv\Scripts\Activate.ps1
Or activate it in Windows Command Prompt:
.venv\Scripts\activate.bat
Then install the package from PyPI:
python -m pip install easy-docker-manager
For work on the source code, follow the development setup.
Running EDM
Run the installed command:
edm
EDM checks the terminal size before it starts. If the window is smaller than 120 columns by 30 rows, EDM prints the current size and exits. Resize the terminal and run the command again.
Show the available command options or installed version, or start EDM without terminal colors:
edm --help
edm --version
edm --diagnostics
edm --no-color
You can also run the Python module directly:
python -m easy_docker_manager
Remote Docker Over SSH
EDM uses the contexts already configured for the Docker command line. It does not keep its own server list or change the context used by other terminals.
Before creating a context, check that SSH works without asking for a password
and that the remote user can reach Docker without sudo:
ssh docker-user@remote-server-address
ssh docker-user@remote-server-address docker ps
Use an SSH key or ssh-agent for authentication. Connect with ssh once before
opening EDM so the server's host key is present in ~/.ssh/known_hosts.
Create a Docker context on the computer where EDM runs:
docker context create remote-server-context \
--description "Remote Docker server" \
--docker "host=ssh://docker-user@remote-server-address"
In this example, remote-server-context is the context name shown in Docker
and EDM. Replace docker-user with the SSH username and
remote-server-address with the remote server's hostname or IP address.
Include the port in the SSH address when the server does not use port 22:
docker context create remote-server-context \
--docker "host=ssh://docker-user@remote-server-address:2222"
Test the context before opening EDM:
docker --context remote-server-context ps
Inside EDM, press c or C, select remote-server-context, and press
Enter. EDM checks the connection in the background. If it succeeds, EDM
clears the old container data and loads containers from the selected
context. If it fails, the current connection stays active and the popup shows
the reason.
If a later container-list refresh fails, EDM keeps the last successful list
on screen and marks the context as stale. The status line shows when that
list was last updated. EDM keeps retrying and changes the context back to
active after the connection recovers. A context is shown as unavailable
when its first refresh has not succeeded yet.
Opening the popup does not connect to every saved server. EDM checks a remote
connection only after you select it and press Enter. EDM cannot ask for or
store an SSH password, so the connection must use a working key or ssh-agent.
Remote Docker Over TLS
SSH and TLS are two separate ways to connect EDM to a remote Docker daemon:
| SSH connection | TLS connection |
|---|---|
| Sends Docker requests through an SSH connection | Sends Docker requests directly to the daemon over an encrypted TCP connection |
Requires a remote SSH user and a working SSH key or ssh-agent |
Requires a CA certificate, client certificate, and private key |
Uses the server entry in ~/.ssh/known_hosts to check the server's identity |
Uses the CA certificate to check the Docker server's identity |
| Does not require the Docker daemon to listen on a TCP port | Requires the Docker daemon to accept TLS connections, usually on port 2376 |
TLS does not use SSH, so it does not require passwordless SSH or an SSH account on the remote server. The TLS certificates provide three protections:
- traffic between EDM and Docker is encrypted;
- the CA certificate confirms that EDM reached the expected Docker server;
- the client certificate and private key prove that EDM is allowed to connect.
This is often called mutual TLS because both sides prove their identity. Treat the client certificate and private key as sensitive files: anyone who can use them may have full control of the remote Docker daemon.
Creating a Docker context does not configure the remote server. It does not contact the server, ask for a password, or copy certificate files to it. The remote Docker daemon must already be listening for verified TLS connections.
See Connect EDM to Remote Docker with TLS for the complete server and client setup.
After the server is ready, create the context on the computer where EDM runs:
docker context create remote-tls-context \
--description "Remote Docker server over TLS" \
--docker "host=tcp://remote-server-address:2376,ca=/path/to/ca.pem,cert=/path/to/cert.pem,key=/path/to/key.pem"
Replace the context name, server address, and certificate paths with your own values. Test the context before opening EDM:
docker --context remote-tls-context version
Inside EDM, press c or C, select remote-tls-context, and press Enter.
Docker's context configuration supplies the certificates; EDM does not add
certificate paths to config.json.
EDM accepts the TCP context only when all three certificate files are present
and the server certificate is verified. A context created with
skip-tls-verify remains unavailable.
Keyboard Controls
| Key | Action |
|---|---|
q |
Quit EDM from the normal screen |
h or H |
Open application help and Docker diagnostics |
p or P |
Open the settings editor |
c or C |
Open Docker context selection |
Up / Down |
Move through containers or detail lines |
Enter |
Move keyboard focus to the detail panel |
Esc |
Return keyboard focus to the container list |
[ |
Open the previous detail tab |
] |
Open the next detail tab |
/ |
Start editing the search for the current tab |
f |
Start editing the container filter while the container panel is active |
s |
Open container list options while the container panel is active |
a or A |
Open actions for the selected running container |
e |
Export the active tab while the detail panel is active |
Page Up / Page Down |
Move through the detail panel one page at a time |
Home / End |
Select the first or last detail line |
While entering a search, press Enter to keep the query and return to detail
navigation. Press Esc to keep the query and return to the container list.
Help And Diagnostics
Press h or H to open the keyboard shortcut list and diagnostics without
leaving EDM. Application versions and file paths appear immediately. Docker
details are loaded in the background, so an unavailable daemon does not stop
keyboard input. Press Esc to close the popup. The Docker check runs again
each time the popup opens. The title panel also shows the installed EDM
version.
Use the command-line report when the terminal interface cannot start:
edm --diagnostics
The report includes the EDM, Python, Docker SDK, and Docker daemon versions. It
also shows the active Docker context, config path, application log path, Docker
API version, platform, and connection result. A failed Docker check prints its
error and exits with status 1; a successful check exits with status 0.
This command does not create or rewrite config.json.
Container Actions
Select a container and press a or A. Running containers offer Restart,
Open shell, and Stop. Created and exited containers offer Start
when All containers is selected. Use Up and Down to choose an action,
then press Enter. EDM either shows a confirmation or, for Open shell, a
full-screen shell workspace. Press Esc to close the popup without making a
change.
The Docker request runs in the background. After it succeeds, EDM reloads the container list. A stopped container disappears while Running only is selected and remains visible while All containers is selected.
Start and Restart use the existing container and its current Docker configuration. They do not reread a Compose file or recreate a Compose service.
Compose-managed containers also offer Recreate Compose service when Docker
provides the project name, service name, working directory, and Compose file
paths in its labels. This runs the equivalent of docker compose up -d --no-deps --force-recreate for that service through the selected Docker
context. It replaces the container, so the ID may change and data kept only in
the old container's writable layer may be lost.
The Compose command runs on the computer where EDM is running. The working directory and Compose files named in the container labels must exist on that computer. This matters for remote Docker contexts because those labels often contain paths from the remote server. EDM reports the missing path instead of running an incomplete command.
Open shell checks for /bin/bash first and uses /bin/sh when Bash is not
available. The shell opens inside EDM and uses the full window. Type exit to
leave the shell, or press Ctrl+D at an empty prompt. EDM returns to the
container view when the shell exits. Commands run there can change the
container.
The shell uses Docker Exec, so the container does not need an SSH server. EDM
passes a named Docker context to the Docker CLI. Connections configured through
DOCKER_HOST keep using that environment instead. If the Docker CLI or both
supported shells are unavailable, EDM shows the error in the container view.
On Windows, EDM uses the current terminal for the shell and restores the app after the command exits. The full-screen shell workspace is used on systems where Urwid can open a PTY.
Container Filtering
Press f while the container panel is active, then type part of a container
name, image name, status, Compose project, or Compose service. Matching ignores
letter case and updates the list as you type. It uses the container data
already loaded in EDM and does not send another request to Docker.
* localhost (active)
────────────────────────
f Filter: off
s Containers: Running only
Sort: Docker order
────────────────────────
> container-one (running)
container-two (running)
Use Backspace to remove the last character. Press Enter to keep the edited
filter, or press Esc to restore the filter that was active before you pressed
f. Other navigation and shortcut keys are disabled until editing ends. Every
printable key, including q, becomes part of the query.
The filter and match count are shown below localhost (active), next to the
f shortcut. The visibility and sort choices appear below it. EDM reapplies
all three after each container-list refresh. If the selected container no
longer matches, the first matching container is selected. Filtering only hides
list entries; cached tab data for hidden containers is kept.
Docker Compose Grouping
Docker Compose grouping is automatic. Containers with the same
com.docker.compose.project label appear together under the project name:
accounts (2)
> accounts-api-1 (running)
accounts-worker-1 (running)
────────────────────────
monitoring (1)
monitoring-grafana-1 (running)
────────────────────────
cadvisor (running)
Containers started without Docker Compose stay at the end of the list. They
are shown as normal container rows without a Standalone heading.
Project headings and separator lines are not selectable. Up and Down move
directly between containers. EDM keeps the current container selected after a
list refresh when that container is still visible and still matches the filter.
Container List Options
Press s while the container panel is active to open this menu:
Container List
> Containers Running only
Sort by Docker order
Direction Not applicable
Up/Down Field Left/Right Change
Enter Apply Esc Cancel
Use Up and Down to choose a row, then use Left or Right to change its
value. Running only keeps the normal compact list. All containers also
shows exited, paused, created, and dead containers. The list remains scrollable
when there are many entries, and the existing f filter can narrow it. Enter
applies every choice, while Esc closes the menu without changing the list.
The chosen visibility and sort stay active after the container list refreshes. Compose projects stay in name order. Docker order restores the order returned by Docker inside each project and among containers without a Compose project.
Stopped containers keep their last logs, Env, and Config available. Logs load
once and do not poll for updates. Stats and Top show Container is not running.
without sending an unsupported request to Docker. Created and exited
containers can be started from the same Actions menu.
The status beside each container also shows health information when Docker
provides it, such as running, healthy or running, unhealthy. Stopped
containers show their exit code, for example exited 137. The Config tab's
State section includes Docker's OOM-killed flag and last error message.
Exporting Tab Content
Press e while the detail panel is active to export the selected container's
Logs, Env, Config, Stats, or Top tab. The popup lets you edit the destination
path and choose one of these scopes:
- Current view exports the lines currently shown after a Logs filter. Env, Config, Stats, and Top searches highlight text without hiding lines, so their current view contains all loaded text.
- Full loaded tab exports all text currently held in EDM's cache. It does not request more data or older logs from Docker.
The suggested path starts in the directory where you launched EDM. Logs use a
.log extension; the other tabs use .txt. Relative paths are also resolved
from that launch directory. When the path is inside your home directory, the
File field shows the home directory as ~ to keep the path shorter.
While File is selected, printable keys, including q and Q, edit the path.
Use Left and Right to move its cursor, Home or End to jump to either
end, and Backspace or Delete to remove characters. Use Up, Down, or
Tab to move between File and Scope.
Exports may contain passwords, tokens, URLs, command arguments, or other sensitive values. EDM shows a warning before every export and writes the text without hiding values. Review exported files before sharing them. EDM never replaces an existing file without asking for confirmation.
Detail Tabs
| Tab | Contents |
|---|---|
| Logs | Recent container logs followed by new log output |
| Env | Configured environment variables and their values |
| Config | Selected container and image inspection data |
| Stats | CPU, memory, network, block I/O, and process usage from Docker |
| Top | Processes reported by Docker top |
Stats reloads every two seconds by default while that tab is visible. Network
and block I/O rates need two samples, so the first sample shows N/A for those
rates. Docker does not report every counter on every operating system or cgroup
version; unavailable values also appear as N/A.
The Stats tab keeps up to 30 CPU and memory samples and draws the newest sample on the right of each trend line. Each line is scaled against its highest saved value, so a short spike remains visible after the numeric value changes. EDM records these samples only while the selected Stats tab is refreshing. It clears them when the container stops or the Docker context changes, and never writes them to disk.
Each container and tab keeps its own search query:
- Logs treats the query as a case-insensitive regular expression and hides lines that do not match.
- Env, Config, Stats, and Top use case-insensitive plain-text search. Matches are highlighted, but no lines are removed.
- An invalid Logs regular expression leaves the log text visible.
- Log regular expressions are limited to 200 characters.
Configuration
Press p or P to edit the saved settings without leaving EDM. Use Up and
Down to select a field. Press Enter to edit a number, then press Enter
again to accept it. Left and Right change Boolean and choice values.
Press s to save, d to load the default values into the form, or Esc to
close the popup without saving. When a number is being edited, the first
Esc cancels that edit and returns to the form. Loading defaults does not
change config.json until s is pressed.
Saved changes take effect after EDM restarts. The Docker client, worker pool, cache, and terminal colors are created during startup, so EDM does not replace them while it is running.
EDM uses platformdirs to place config.json in the correct user config
directory for the operating system. The file is stored in an EDM folder.
Typical locations are:
| Operating system | Typical path |
|---|---|
| Linux | ~/.config/EDM/config.json |
| macOS | ~/Library/Application Support/EDM/config.json |
| Windows | %LOCALAPPDATA%\EDM\config.json |
EDM creates this file on first use. On later starts, it keeps valid settings, fills in missing defaults, removes unknown or invalid values, and writes the cleaned configuration back to the file.
| Setting | Default | Purpose |
|---|---|---|
container_list_refresh_interval_seconds |
2.0 |
Seconds between container-list refreshes |
detail_tab_refresh_interval_seconds |
2.0 |
Seconds between reloads of the visible Env, Config, Stats, or Top tab |
initial_log_tail_lines |
100 |
Number of recent lines loaded when Logs first opens |
max_log_lines |
2000 |
Maximum log lines kept for one container |
max_log_line_chars |
4000 |
Maximum characters kept from one log line (minimum 32) |
log_timestamp_mode |
"Docker UTC" |
Display Docker's UTC timestamp, local time, or no timestamp |
tab_content_cache_max_entries |
50 |
Maximum number of cached container tabs |
tab_content_cache_max_bytes |
25000000 |
Maximum UTF-8 size of all cached tab text |
docker_request_timeout_seconds |
10.0 |
Docker SDK request timeout in seconds |
max_background_worker_threads |
4 |
Maximum number of background worker threads |
colors_enabled |
true |
Use terminal colors; set to false for monochrome output |
application_log_level |
"INFO" |
Minimum level written to EDM's application log |
application_log_to_stdout |
false |
Also write EDM application messages to standard output |
EDM keeps values saved under the former tab_refresh_interval and
docker_request_timeout names. On the next startup, it writes them back using
the current names shown above. If both names are present, the current name wins.
edm --no-color disables colors for one run without changing config.json.
Docker UTC keeps the timestamp returned by Docker. Local time converts that timestamp to the timezone of the computer running EDM and includes its UTC offset. Hidden removes the timestamp and the space after it. These modes only change a valid Docker timestamp at the start of a line. A timestamp written by the application later in the log message stays unchanged.
Application Logs
EDM writes its own application messages to edm.log beside config.json.
This file contains EDM errors and diagnostic messages, not container logs. It
rotates at 5 MB and keeps three backup files.
Paramiko errors from remote SSH connections are written to the same file. They are kept out of the terminal so they do not overwrite the EDM screen.
The application log level and stdout output can be changed in the settings
editor or config.json. These environment variables override saved values for
one run:
| Variable | Purpose |
|---|---|
EDM_LOG_FILE |
Write to a different log file |
EDM_LOG_LEVEL |
Set the level, such as DEBUG or WARNING |
EDM_LOG_STDOUT |
Also write logs to standard output when enabled |
EDM_LOG_STDOUT is disabled for 0, false, no, or off. Other values
enable it. If EDM cannot create the log file, it prints a warning to the
terminal and continues to start.
Development Checks
Use Python 3.10 or newer for the development tools. Installed EDM releases still support Python 3.9.
Run the normal formatting, linting, type, and source-security checks:
make check
Useful individual commands are:
make black
make black-check
make ruff
make ruff-fix
make mypy
make bandit
make test
make integration-test
make remote-integration-test
make all-integration-tests
make smoke-test
make pre-commit
make audit
make security
make package-check
make audit checks installed dependencies for known vulnerabilities. It needs
Python 3.10 or newer and network access, so it is not part of make check.
make test prints statement and branch coverage after the unit tests finish.
make integration-test starts a temporary Alpine container and checks container
listing, logs, environment variables, inspection data, and process information.
It requires access to a running local Docker daemon.
make remote-integration-test starts isolated Docker-in-Docker services and
checks Docker contexts over SSH and verified TLS. It uses temporary Docker and
SSH configuration, then removes the services and configuration when it exits.
make all-integration-tests runs both Docker suites.
make smoke-test checks package imports, platform paths, notifier selection,
and basic startup on the current operating system.
GitHub Actions runs Black, Ruff, mypy, and Bandit once on Python 3.12. It runs the unit tests on Python 3.9 through 3.14 and runs the local and remote Docker integration suites on Python 3.12. It also runs wheel smoke tests on Windows and macOS, verifies the minimum supported runtime dependency versions on Python 3.9, checks dependencies and committed secrets, builds the source distribution and wheel, and installs the wheel on every supported Python version. Dependabot checks Python packages and GitHub Actions each week.
Workflow actions are pinned to full commit SHAs so CI always runs the exact reviewed action code instead of a movable version tag. The comment beside each SHA shows its release version, and Dependabot proposes SHA updates when newer releases are available.
See DEVELOPMENT_GUIDE.md for the code structure, runtime flow, and instructions for extending EDM.
Contributing
Bug reports, feature ideas, and code contributions are welcome. Read CONTRIBUTING.md before opening a pull request.
Please report security problems privately by following SECURITY.md. Do not include sensitive vulnerability details in a public issue.
License
Easy Docker Manager is available under the MIT License.
Metadata
Release files for easy-docker-manager 2.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| easy_docker_manager-2.1.0.tar.gz | 4.8 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| easy_docker_manager-2.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.0 MB
Release files / easy_docker_manager-2.1.0.tar.gz
| Download URL | easy_docker_manager-2.1.0.tar.gz |
|---|---|
| Size | 4.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
540822335688a80fd293f94ebc4dc02358feac2db6917a1872b5ed7cac42dac4
|
|
BLAKE2b-256 checksum How to use checksums |
7d550042096772c6db8500b396b5e7100734d3bfe648b670138c66452db0fecd
|
| 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 Oct 1, 2026.
Transparency logRelease files / easy_docker_manager-2.1.0-py3-none-any.whl
| Download URL | easy_docker_manager-2.1.0-py3-none-any.whl |
|---|---|
| Size | 135.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5055eec0b253c746750c6659e9d3ffae429552174cf8cd1347fbd78e747afc8a
|
|
BLAKE2b-256 checksum How to use checksums |
29bdcecab6a8996ffedf45686063b427e7e4cccc02ca62023250e7fe1e122374
|
| 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 Oct 1, 2026.
Transparency log