docker-orb 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docker_orb-1.0.0/.gitignore +9 -0
- docker_orb-1.0.0/CLAUDE.md +134 -0
- docker_orb-1.0.0/LICENSE +21 -0
- docker_orb-1.0.0/PKG-INFO +192 -0
- docker_orb-1.0.0/README.md +139 -0
- docker_orb-1.0.0/docs/USER_GUIDE.md +309 -0
- docker_orb-1.0.0/docs/demo.tape +269 -0
- docker_orb-1.0.0/docs/screenshot-viewer.png +0 -0
- docker_orb-1.0.0/infra/Makefile +57 -0
- docker_orb-1.0.0/infra/README.md +126 -0
- docker_orb-1.0.0/infra/docker-compose.yml +87 -0
- docker_orb-1.0.0/infra/services/api-gateway/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/api-gateway/app.py +125 -0
- docker_orb-1.0.0/infra/services/auth-service/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/auth-service/app.py +126 -0
- docker_orb-1.0.0/infra/services/cache/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/cache/app.py +110 -0
- docker_orb-1.0.0/infra/services/database/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/database/app.py +131 -0
- docker_orb-1.0.0/infra/services/notification-service/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/notification-service/app.py +174 -0
- docker_orb-1.0.0/infra/services/scheduler/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/scheduler/app.py +137 -0
- docker_orb-1.0.0/infra/services/user-service/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/user-service/app.py +132 -0
- docker_orb-1.0.0/infra/services/worker/Dockerfile +5 -0
- docker_orb-1.0.0/infra/services/worker/app.py +143 -0
- docker_orb-1.0.0/pyproject.toml +76 -0
- docker_orb-1.0.0/scripts/run-safe.sh +21 -0
- docker_orb-1.0.0/src/docker_orb/__init__.py +0 -0
- docker_orb-1.0.0/src/docker_orb/__main__.py +5 -0
- docker_orb-1.0.0/src/docker_orb/_scrollbar.py +136 -0
- docker_orb-1.0.0/src/docker_orb/cli.py +167 -0
- docker_orb-1.0.0/src/docker_orb/colors.py +60 -0
- docker_orb-1.0.0/src/docker_orb/compose.py +391 -0
- docker_orb-1.0.0/src/docker_orb/config.py +244 -0
- docker_orb-1.0.0/src/docker_orb/inject.py +160 -0
- docker_orb-1.0.0/src/docker_orb/jsonlog.py +125 -0
- docker_orb-1.0.0/src/docker_orb/models.py +132 -0
- docker_orb-1.0.0/src/docker_orb/viewer/__init__.py +0 -0
- docker_orb-1.0.0/src/docker_orb/viewer/app.py +824 -0
- docker_orb-1.0.0/src/docker_orb/viewer/panels/__init__.py +0 -0
- docker_orb-1.0.0/src/docker_orb/viewer/panels/health.py +239 -0
- docker_orb-1.0.0/src/docker_orb/viewer/panels/main_stream.py +389 -0
- docker_orb-1.0.0/src/docker_orb/viewer/panels/monitor.py +233 -0
- docker_orb-1.0.0/src/docker_orb/viewer/panels/search.py +182 -0
- docker_orb-1.0.0/src/docker_orb/viewer/viewer.tcss +205 -0
- docker_orb-1.0.0/src/docker_orb/viewer/widgets.py +668 -0
- docker_orb-1.0.0/src/docker_orb/wizard/__init__.py +0 -0
- docker_orb-1.0.0/src/docker_orb/wizard/app.py +40 -0
- docker_orb-1.0.0/src/docker_orb/wizard/screens.py +692 -0
- docker_orb-1.0.0/src/docker_orb/wizard/wizard.tcss +329 -0
- docker_orb-1.0.0/tests/__init__.py +0 -0
- docker_orb-1.0.0/tests/features/wizard.feature +48 -0
- docker_orb-1.0.0/tests/test_colors.py +50 -0
- docker_orb-1.0.0/tests/test_compose.py +188 -0
- docker_orb-1.0.0/tests/test_config.py +173 -0
- docker_orb-1.0.0/tests/test_health_panel.py +43 -0
- docker_orb-1.0.0/tests/test_jsonlog.py +69 -0
- docker_orb-1.0.0/tests/test_scrollbar.py +59 -0
- docker_orb-1.0.0/tests/test_viewer_backfill.py +162 -0
- docker_orb-1.0.0/tests/test_viewer_collapse_repeats.py +173 -0
- docker_orb-1.0.0/tests/test_viewer_color_mode.py +155 -0
- docker_orb-1.0.0/tests/test_viewer_edit_behaviors.py +145 -0
- docker_orb-1.0.0/tests/test_viewer_json_format.py +170 -0
- docker_orb-1.0.0/tests/test_viewer_keybindings.py +56 -0
- docker_orb-1.0.0/tests/test_viewer_monitor_context.py +189 -0
- docker_orb-1.0.0/tests/test_viewer_monitor_double_click.py +68 -0
- docker_orb-1.0.0/tests/test_viewer_pane_size_modal.py +149 -0
- docker_orb-1.0.0/tests/test_viewer_pause_resume.py +103 -0
- docker_orb-1.0.0/tests/test_viewer_resize.py +76 -0
- docker_orb-1.0.0/tests/test_viewer_string_edit_modal.py +88 -0
- docker_orb-1.0.0/tests/test_wizard_bdd_scenarios.py +163 -0
- docker_orb-1.0.0/tests/test_wizard_screens.py +109 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install in editable mode (sets up both entry points)
|
|
9
|
+
# NOTE: dev deps are a PEP 735 dependency group, not an extra — `.[dev]`
|
|
10
|
+
# silently installs nothing (pip just warns "does not provide the extra").
|
|
11
|
+
pip install -e . --group dev
|
|
12
|
+
# or with uv:
|
|
13
|
+
uv pip install -e . --group dev
|
|
14
|
+
|
|
15
|
+
# Run the TUI app (dev mode with live reload via textual-dev)
|
|
16
|
+
hatch run dev
|
|
17
|
+
# or directly:
|
|
18
|
+
textual run --dev src/docker_orb/__main__.py
|
|
19
|
+
|
|
20
|
+
# Run the app normally
|
|
21
|
+
docker-orb
|
|
22
|
+
|
|
23
|
+
# Run all tests
|
|
24
|
+
pytest
|
|
25
|
+
# or via hatch:
|
|
26
|
+
hatch run test
|
|
27
|
+
|
|
28
|
+
# Run a single test file
|
|
29
|
+
pytest tests/test_config.py
|
|
30
|
+
|
|
31
|
+
# Run a single test class or method
|
|
32
|
+
pytest tests/test_config.py::TestParseStringInput::test_comma_separated
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Test infrastructure (local Compose stack)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd infra
|
|
39
|
+
make up # one-shot: build + start 8 fake log-generating services
|
|
40
|
+
make status # docker compose ps
|
|
41
|
+
make logs # tail all services
|
|
42
|
+
make logs SERVICE=worker # tail one service
|
|
43
|
+
make restart # recreate all services (picks up code changes)
|
|
44
|
+
make teardown # stop and remove everything
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The stack runs under the fixed Compose project name `logviewer-demo` (8
|
|
48
|
+
services: `api-gateway`, `auth-service`, `user-service`,
|
|
49
|
+
`notification-service`, `worker`, `database`, `cache`, `scheduler` — the
|
|
50
|
+
busier five run 2 containers each). It's deliberately not named
|
|
51
|
+
`docker-orb-*` — docker-orb doesn't prepend its own name to anything, and
|
|
52
|
+
container names here (`logviewer-demo-api-gateway-1`, etc.) are just this
|
|
53
|
+
demo's own Compose project name, same as any other stack. It also stops
|
|
54
|
+
itself automatically after 4 hours by default (a `reaper` service in
|
|
55
|
+
`docker-compose.yml`, socket-mounted, `docker stop`s the project's
|
|
56
|
+
containers on a timer — see `infra/README.md#auto-shutdown-after-4-hours`
|
|
57
|
+
for overriding/disabling it) so it's never left running unattended
|
|
58
|
+
indefinitely. Point docker-orb at it with:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
docker-orb -n logviewer-demo --all-containers --health
|
|
62
|
+
docker-orb-inject -n logviewer-demo -d worker -m "ERROR: test error"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`docker-orb-inject` writes directly to a container's PID 1 stdout via
|
|
66
|
+
`docker exec ... sh -c "echo ... > /proc/1/fd/1"`, so injected messages show
|
|
67
|
+
up in the live stream exactly like real application logs — handy for
|
|
68
|
+
exercising filters/highlights/monitors without waiting for a real error.
|
|
69
|
+
|
|
70
|
+
This is a straight Compose port of kube-orb's k3d test cluster: same
|
|
71
|
+
Python log-generator scripts under `infra/services/`, unchanged (none of
|
|
72
|
+
them depended on anything Kubernetes-specific), just wired up with
|
|
73
|
+
`infra/docker-compose.yml` instead of k3d + k8s manifests. It also still
|
|
74
|
+
works fine, of course, to point docker-orb at any other real
|
|
75
|
+
`docker-compose.yml` project you have running.
|
|
76
|
+
|
|
77
|
+
## Architecture
|
|
78
|
+
|
|
79
|
+
docker-orb is a **Textual TUI** app with two entry points:
|
|
80
|
+
|
|
81
|
+
- `docker-orb` (`src/docker_orb/cli.py`) — main CLI. If enough args are provided, launches the viewer directly; otherwise falls through to the wizard.
|
|
82
|
+
- `docker-orb-inject` (`src/docker_orb/inject.py`) — test utility that writes messages to a container's stdout via `docker exec`, causing them to appear in the live log stream.
|
|
83
|
+
|
|
84
|
+
### Data flow
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
CLI args / Wizard
|
|
88
|
+
↓
|
|
89
|
+
SessionConfig (models.py)
|
|
90
|
+
↓
|
|
91
|
+
ViewerApp (viewer/app.py)
|
|
92
|
+
↓ asyncio workers (one per container)
|
|
93
|
+
compose.stream_logs() (compose.py) — async subprocess, `docker logs -f`
|
|
94
|
+
↓ LogLine objects
|
|
95
|
+
_ingest() → filter → _deliver_to_panels()
|
|
96
|
+
↓
|
|
97
|
+
MainStreamPanel / MonitorPanel / HealthPanel / SearchPanel
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Key modules
|
|
101
|
+
|
|
102
|
+
| Module | Purpose |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `models.py` | All shared dataclasses: `SessionConfig`, `LogLine`, `Service`, `Container`, `ContainerStatus`, `HealthConfig` |
|
|
105
|
+
| `compose.py` | All Docker/Compose interaction via subprocess (`docker`, `docker compose`). No Python Docker SDK. `stream_logs()` runs `docker logs -f --timestamps <container>` per container (one coroutine per container, same fan-out pattern as kube-orb's per-pod streaming) rather than a single multiplexed `docker compose logs -f`; `dump_logs()` is one-shot. `stream_logs()` normalizes `since` to `"1s"` when unset/zero (`_normalize_since()`) so a live session only collects new lines instead of replaying history. **Untested against a live Docker daemon in the environment this was written in** — verify service/container discovery (`docker compose ps --format json` shape) and the `--since` normalization against a real Compose project before relying on it. |
|
|
106
|
+
| `config.py` | Persists session configs to `~/.config/docker-orb/projects/<project>/<name>.yaml` and global saved strings to `~/.config/docker-orb/strings.yaml`. Also owns pattern compilation: plain strings are `re.escape`d; `/regex/`-wrapped strings compile as real regex. |
|
|
107
|
+
| `colors.py` | Assigns a distinct ANSI/CSS color to each container name. |
|
|
108
|
+
| `jsonlog.py` | Detects single-JSON-object log lines and extracts level/message/timestamp (checking a few conventional key names) for the optional readable-formatting toggle. Detection runs regardless of the toggle, since the Enter-for-detail view needs it too. |
|
|
109
|
+
| `viewer/app.py` | `ViewerApp` — the main Textual `App`. Owns the log buffer, pause state, pattern state, and container/service lifecycle. |
|
|
110
|
+
| `viewer/panels/` | Four panels: `MainStreamPanel` (primary log display), `SearchPanel` (live search), `MonitorPanel` (passive pattern accumulation), `HealthPanel` (restart/health alerts). |
|
|
111
|
+
| `viewer/widgets.py` | Shared widgets: `StringEditModal` (F/H/M editing), `SaveDialog`, `ContainerSelectorModal`, `PaneSizeModal`, `JsonDetailModal`, `MonitorContextModal`. |
|
|
112
|
+
| `wizard/` | Three-tab Textual wizard (`SinglePageWizard` screen) — Targets → Strings → Options — produces a `SessionConfig`. |
|
|
113
|
+
|
|
114
|
+
### Pattern matching
|
|
115
|
+
|
|
116
|
+
Filters, highlights, and monitors all share the same matching syntax (in `config.py`):
|
|
117
|
+
- Plain strings are matched as literals (dots and special chars are escaped).
|
|
118
|
+
- `/pattern/` strings are compiled as regex.
|
|
119
|
+
- Comma-separated input is parsed by `parse_string_input()`.
|
|
120
|
+
|
|
121
|
+
### Package layout
|
|
122
|
+
|
|
123
|
+
`src/docker_orb/` is the canonical source package.
|
|
124
|
+
|
|
125
|
+
### Provenance
|
|
126
|
+
|
|
127
|
+
docker-orb started as a sibling port of [kube-orb](https://github.com/adlidev/kube-orb):
|
|
128
|
+
the Textual viewer/wizard/panel layer (~3900 lines) was carried over largely
|
|
129
|
+
unchanged since it only ever depended on generic `LogLine`/container-name
|
|
130
|
+
concepts, not Kubernetes specifics. The Kubernetes-coupled layer — `kubectl.py`, the `Deployment`/`Pod` models, and
|
|
131
|
+
the k3d test infra — was replaced with `compose.py`, `Service`/`Container`
|
|
132
|
+
models, and an `infra/docker-compose.yml` port of the same test-log
|
|
133
|
+
services. The two projects are maintained independently going forward;
|
|
134
|
+
changes to one don't automatically apply to the other.
|
docker_orb-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Adli Waziri
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docker-orb
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Interactive terminal UI for streaming and filtering Docker Compose container logs across multiple services
|
|
5
|
+
Project-URL: Homepage, https://github.com/adlidev/docker-orb
|
|
6
|
+
Project-URL: Repository, https://github.com/adlidev/docker-orb
|
|
7
|
+
Project-URL: Documentation, https://github.com/adlidev/docker-orb/blob/main/docs/USER_GUIDE.md
|
|
8
|
+
Project-URL: Issues, https://github.com/adlidev/docker-orb/issues
|
|
9
|
+
Author-email: Adli Waziri <boulderadli@gmail.com>
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Adli Waziri
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: compose,devops,docker,docker-compose,logs,observability,sre,textual,tui
|
|
33
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: Intended Audience :: System Administrators
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: MacOS
|
|
39
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
40
|
+
Classifier: Programming Language :: Python :: 3
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
44
|
+
Classifier: Topic :: System :: Logging
|
|
45
|
+
Classifier: Topic :: System :: Monitoring
|
|
46
|
+
Classifier: Topic :: System :: Systems Administration
|
|
47
|
+
Classifier: Topic :: Utilities
|
|
48
|
+
Requires-Python: >=3.10
|
|
49
|
+
Requires-Dist: click>=8.1
|
|
50
|
+
Requires-Dist: pyyaml>=6.0
|
|
51
|
+
Requires-Dist: textual>=0.61.0
|
|
52
|
+
Description-Content-Type: text/markdown
|
|
53
|
+
|
|
54
|
+
# docker-orb
|
|
55
|
+
|
|
56
|
+
Watching logs across a multi-container Compose stack usually means juggling
|
|
57
|
+
multiple `docker compose logs` windows and grepping after the fact, or
|
|
58
|
+
writing complex regex just to add a couple of filters. docker-orb streams
|
|
59
|
+
logs from every container in your selected services into one merged,
|
|
60
|
+
colorized view — and lets you filter, highlight, and search *while it's
|
|
61
|
+
streaming*.
|
|
62
|
+
|
|
63
|
+
Built with [Textual](https://textual.textualize.io/), docker-orb is a full
|
|
64
|
+
terminal UI: an interactive setup wizard walks you through picking a
|
|
65
|
+
project, services, and filter patterns — no flags required — or skip
|
|
66
|
+
straight to the viewer with CLI arguments if you prefer. Save named session
|
|
67
|
+
configs to reload your exact setup later; passively collect rare events in
|
|
68
|
+
a monitor panel without losing your scroll position; get alerted when
|
|
69
|
+
containers restart or go unhealthy; and add or remove services from the
|
|
70
|
+
live stream without restarting.
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
- **Multi-container live tail** — stream logs from any number of
|
|
77
|
+
containers/services at once, each with a distinct color.
|
|
78
|
+
- **Filters** — hide lines matching a pattern, live-editable mid-session.
|
|
79
|
+
- **Highlights** — emphasize lines matching a pattern without hiding anything else.
|
|
80
|
+
- **Monitors** — passively collect matching lines into a separate panel so you
|
|
81
|
+
can watch for rare events (e.g. `job failed`) without losing your scroll
|
|
82
|
+
position in the main stream.
|
|
83
|
+
- **Live search** — search the whole buffered session, jump to a result, and
|
|
84
|
+
keep streaming.
|
|
85
|
+
- **Container health panel** — flags containers that aren't `Running` or have
|
|
86
|
+
crossed a restart threshold; restart a container or recreate a service from
|
|
87
|
+
inside the app.
|
|
88
|
+
- **Dump mode** — fetch existing logs once (with `--tail`/`--since`) and exit,
|
|
89
|
+
for scripting or one-off inspection, instead of a live stream.
|
|
90
|
+
- **Saved configs** — save a named combination of project, services, and
|
|
91
|
+
patterns, and reload it later by name.
|
|
92
|
+
- **JSON log formatting** — auto-detects structured JSON log lines and shows
|
|
93
|
+
`time LEVEL message key=value ...` instead of a raw JSON blob, with a
|
|
94
|
+
toggle back to raw and a detail view (Enter on a clicked line) for the full
|
|
95
|
+
pretty-printed object.
|
|
96
|
+
- **Collapse repeated lines** — journalctl-style: consecutive identical lines
|
|
97
|
+
from the same container fold into a single "last line repeated N times"
|
|
98
|
+
marker, toggleable, so a crash-looping container doesn't flood the stream.
|
|
99
|
+
|
|
100
|
+
## Installation
|
|
101
|
+
|
|
102
|
+
Requires Python 3.10+, and `docker` with the Compose v2 plugin on your
|
|
103
|
+
`PATH` (i.e. `docker compose` works). docker-orb shells out to your existing
|
|
104
|
+
`docker` CLI and inherits its context/auth — no separate credentials or
|
|
105
|
+
Docker SDK involved.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Recommended — pipx keeps CLI tools in isolated environments. Not on PyPI
|
|
109
|
+
# yet, so install straight from GitHub:
|
|
110
|
+
pipx install git+https://github.com/adlidev/docker-orb
|
|
111
|
+
|
|
112
|
+
# Or with plain pip, inside your own venv:
|
|
113
|
+
git clone https://github.com/adlidev/docker-orb.git
|
|
114
|
+
cd docker-orb
|
|
115
|
+
pip install -e .
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This installs two commands: `docker-orb` and `docker-orb-inject` (a small
|
|
119
|
+
test utility for injecting fake log lines into a running container — see
|
|
120
|
+
the [User Guide](docs/USER_GUIDE.md#docker-orb-inject)).
|
|
121
|
+
|
|
122
|
+
**For development / contributing:**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
git clone https://github.com/adlidev/docker-orb.git
|
|
126
|
+
cd docker-orb
|
|
127
|
+
pip install -e . --group dev
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Quick start
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# No arguments — launches the interactive setup wizard
|
|
134
|
+
docker-orb
|
|
135
|
+
|
|
136
|
+
# Skip the wizard: watch two services live
|
|
137
|
+
docker-orb -n myapp -p api -p worker
|
|
138
|
+
|
|
139
|
+
# Watch every service in a project
|
|
140
|
+
docker-orb -n myapp --all-containers
|
|
141
|
+
|
|
142
|
+
# One-shot dump instead of a live stream
|
|
143
|
+
docker-orb -n myapp --dump --tail 500
|
|
144
|
+
|
|
145
|
+
# Pre-filter/highlight from the command line
|
|
146
|
+
docker-orb -n myapp -p worker -f DEBUG -H ERROR --health
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`-n/--project` takes the Compose project name (what `docker compose -p`
|
|
150
|
+
expects — usually the directory name your `docker-compose.yml` lives in,
|
|
151
|
+
unless overridden by a top-level `name:` key or `COMPOSE_PROJECT_NAME`). If
|
|
152
|
+
omitted, docker-orb resolves it the same way `docker compose` does for the
|
|
153
|
+
current directory.
|
|
154
|
+
|
|
155
|
+
Once you're in the viewer, press `F` / `H` / `M` to edit filters, highlights,
|
|
156
|
+
or monitors live, `/` to search, `P` to add/remove streamed services, and
|
|
157
|
+
`Space` to pause. See the [User Guide](docs/USER_GUIDE.md) for the full
|
|
158
|
+
keybinding reference and pattern syntax.
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
pip install -e . --group dev
|
|
164
|
+
pytest # run the test suite
|
|
165
|
+
textual run --dev src/docker_orb/__main__.py # live-reload dev mode
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
A local Compose stack with 8 fake log-generating services is included for
|
|
169
|
+
manual testing:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
cd infra
|
|
173
|
+
make up
|
|
174
|
+
docker-orb -n logviewer-demo --all-containers --health
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
See [`infra/README.md`](infra/README.md) for the service list and good
|
|
178
|
+
filter/monitor test patterns, and [`CLAUDE.md`](CLAUDE.md) for architecture
|
|
179
|
+
notes.
|
|
180
|
+
|
|
181
|
+
## Relationship to kube-orb
|
|
182
|
+
|
|
183
|
+
docker-orb is a sibling project to [kube-orb](https://github.com/adlidev/kube-orb),
|
|
184
|
+
Adli's Kubernetes-flavored log viewer. They share a UI architecture (Textual
|
|
185
|
+
viewer, wizard, filters/highlights/monitors, JSON formatting) but each talks
|
|
186
|
+
to its own backend directly — docker-orb shells out to `docker`/`docker
|
|
187
|
+
compose`, kube-orb shells out to `kubectl` — and they're maintained as
|
|
188
|
+
independent tools rather than one project trying to do both.
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
[MIT License](LICENSE)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# docker-orb
|
|
2
|
+
|
|
3
|
+
Watching logs across a multi-container Compose stack usually means juggling
|
|
4
|
+
multiple `docker compose logs` windows and grepping after the fact, or
|
|
5
|
+
writing complex regex just to add a couple of filters. docker-orb streams
|
|
6
|
+
logs from every container in your selected services into one merged,
|
|
7
|
+
colorized view — and lets you filter, highlight, and search *while it's
|
|
8
|
+
streaming*.
|
|
9
|
+
|
|
10
|
+
Built with [Textual](https://textual.textualize.io/), docker-orb is a full
|
|
11
|
+
terminal UI: an interactive setup wizard walks you through picking a
|
|
12
|
+
project, services, and filter patterns — no flags required — or skip
|
|
13
|
+
straight to the viewer with CLI arguments if you prefer. Save named session
|
|
14
|
+
configs to reload your exact setup later; passively collect rare events in
|
|
15
|
+
a monitor panel without losing your scroll position; get alerted when
|
|
16
|
+
containers restart or go unhealthy; and add or remove services from the
|
|
17
|
+
live stream without restarting.
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **Multi-container live tail** — stream logs from any number of
|
|
24
|
+
containers/services at once, each with a distinct color.
|
|
25
|
+
- **Filters** — hide lines matching a pattern, live-editable mid-session.
|
|
26
|
+
- **Highlights** — emphasize lines matching a pattern without hiding anything else.
|
|
27
|
+
- **Monitors** — passively collect matching lines into a separate panel so you
|
|
28
|
+
can watch for rare events (e.g. `job failed`) without losing your scroll
|
|
29
|
+
position in the main stream.
|
|
30
|
+
- **Live search** — search the whole buffered session, jump to a result, and
|
|
31
|
+
keep streaming.
|
|
32
|
+
- **Container health panel** — flags containers that aren't `Running` or have
|
|
33
|
+
crossed a restart threshold; restart a container or recreate a service from
|
|
34
|
+
inside the app.
|
|
35
|
+
- **Dump mode** — fetch existing logs once (with `--tail`/`--since`) and exit,
|
|
36
|
+
for scripting or one-off inspection, instead of a live stream.
|
|
37
|
+
- **Saved configs** — save a named combination of project, services, and
|
|
38
|
+
patterns, and reload it later by name.
|
|
39
|
+
- **JSON log formatting** — auto-detects structured JSON log lines and shows
|
|
40
|
+
`time LEVEL message key=value ...` instead of a raw JSON blob, with a
|
|
41
|
+
toggle back to raw and a detail view (Enter on a clicked line) for the full
|
|
42
|
+
pretty-printed object.
|
|
43
|
+
- **Collapse repeated lines** — journalctl-style: consecutive identical lines
|
|
44
|
+
from the same container fold into a single "last line repeated N times"
|
|
45
|
+
marker, toggleable, so a crash-looping container doesn't flood the stream.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
Requires Python 3.10+, and `docker` with the Compose v2 plugin on your
|
|
50
|
+
`PATH` (i.e. `docker compose` works). docker-orb shells out to your existing
|
|
51
|
+
`docker` CLI and inherits its context/auth — no separate credentials or
|
|
52
|
+
Docker SDK involved.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Recommended — pipx keeps CLI tools in isolated environments. Not on PyPI
|
|
56
|
+
# yet, so install straight from GitHub:
|
|
57
|
+
pipx install git+https://github.com/adlidev/docker-orb
|
|
58
|
+
|
|
59
|
+
# Or with plain pip, inside your own venv:
|
|
60
|
+
git clone https://github.com/adlidev/docker-orb.git
|
|
61
|
+
cd docker-orb
|
|
62
|
+
pip install -e .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This installs two commands: `docker-orb` and `docker-orb-inject` (a small
|
|
66
|
+
test utility for injecting fake log lines into a running container — see
|
|
67
|
+
the [User Guide](docs/USER_GUIDE.md#docker-orb-inject)).
|
|
68
|
+
|
|
69
|
+
**For development / contributing:**
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git clone https://github.com/adlidev/docker-orb.git
|
|
73
|
+
cd docker-orb
|
|
74
|
+
pip install -e . --group dev
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Quick start
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# No arguments — launches the interactive setup wizard
|
|
81
|
+
docker-orb
|
|
82
|
+
|
|
83
|
+
# Skip the wizard: watch two services live
|
|
84
|
+
docker-orb -n myapp -p api -p worker
|
|
85
|
+
|
|
86
|
+
# Watch every service in a project
|
|
87
|
+
docker-orb -n myapp --all-containers
|
|
88
|
+
|
|
89
|
+
# One-shot dump instead of a live stream
|
|
90
|
+
docker-orb -n myapp --dump --tail 500
|
|
91
|
+
|
|
92
|
+
# Pre-filter/highlight from the command line
|
|
93
|
+
docker-orb -n myapp -p worker -f DEBUG -H ERROR --health
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`-n/--project` takes the Compose project name (what `docker compose -p`
|
|
97
|
+
expects — usually the directory name your `docker-compose.yml` lives in,
|
|
98
|
+
unless overridden by a top-level `name:` key or `COMPOSE_PROJECT_NAME`). If
|
|
99
|
+
omitted, docker-orb resolves it the same way `docker compose` does for the
|
|
100
|
+
current directory.
|
|
101
|
+
|
|
102
|
+
Once you're in the viewer, press `F` / `H` / `M` to edit filters, highlights,
|
|
103
|
+
or monitors live, `/` to search, `P` to add/remove streamed services, and
|
|
104
|
+
`Space` to pause. See the [User Guide](docs/USER_GUIDE.md) for the full
|
|
105
|
+
keybinding reference and pattern syntax.
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install -e . --group dev
|
|
111
|
+
pytest # run the test suite
|
|
112
|
+
textual run --dev src/docker_orb/__main__.py # live-reload dev mode
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
A local Compose stack with 8 fake log-generating services is included for
|
|
116
|
+
manual testing:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
cd infra
|
|
120
|
+
make up
|
|
121
|
+
docker-orb -n logviewer-demo --all-containers --health
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
See [`infra/README.md`](infra/README.md) for the service list and good
|
|
125
|
+
filter/monitor test patterns, and [`CLAUDE.md`](CLAUDE.md) for architecture
|
|
126
|
+
notes.
|
|
127
|
+
|
|
128
|
+
## Relationship to kube-orb
|
|
129
|
+
|
|
130
|
+
docker-orb is a sibling project to [kube-orb](https://github.com/adlidev/kube-orb),
|
|
131
|
+
Adli's Kubernetes-flavored log viewer. They share a UI architecture (Textual
|
|
132
|
+
viewer, wizard, filters/highlights/monitors, JSON formatting) but each talks
|
|
133
|
+
to its own backend directly — docker-orb shells out to `docker`/`docker
|
|
134
|
+
compose`, kube-orb shells out to `kubectl` — and they're maintained as
|
|
135
|
+
independent tools rather than one project trying to do both.
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
[MIT License](LICENSE)
|