Programmatic Docker image layer analysis, auditing, and diffing for Python
Project description
dockerlens
Programmatic Docker image layer analysis, auditing, and diffing for Python.
dockerlens is a typed Python library that lets you inspect Docker images from your own code — no CLI scraping, no shell-outs. Think of it as a Pythonic alternative to tools like dive or container-diff, designed to be imported into your scripts, CI pipelines, and dashboards.
Installation
pip install dockerlens-py
Requires Python 3.9+ and a running Docker daemon (for image inspection, not for tests).
CLI Usage
dockerlens now provides a command-line interface for quick analysis:
# Analyze an image (prints rich tables to terminal)
dockerlens analyze nginx:latest
# Analyze an image directly from Docker Hub without pulling it locally!
dockerlens analyze --remote nginx:latest
# Export analysis as JSON, Markdown, or HTML
dockerlens analyze nginx:latest --format markdown > report.md
dockerlens analyze nginx:latest --format json > report.json
# Compare two images
dockerlens diff nginx:1.24 nginx:latest
Quick Start (Python API)
from dockerlens import ImageAnalyzer
# Analyze an image (local)
analyzer = ImageAnalyzer("nginx:latest")
# Analyze an image directly from remote registry (daemonless)
remote_analyzer = ImageAnalyzer("nginx:latest", remote=True)
# Inspect layers
for layer in analyzer.layers():
print(f"Layer {layer.index}: {layer.size_human:>10} {layer.command}")
# Run security & best-practice audit
for issue in analyzer.audit():
print(f"[{issue.severity}] {issue.rule_id}: {issue.message}")
# Compare two images
for change in analyzer.diff("nginx:1.24"):
print(f" {change.change_type:>8} {change.path}")
# Generate a full report as JSON
report = analyzer.report()
print(report.to_json())
# Pretty-print to the terminal with rich
analyzer.print_layers()
analyzer.print_audit()
analyzer.print_diff("nginx:1.24")
API Reference
ImageAnalyzer(image, docker_client=None, remote=False)
Main entry point. Pass an image name/tag (e.g. "nginx:latest"). If remote=True, it will fetch metadata directly from Docker Hub via the HTTP API, requiring no local Docker daemon!
| Method | Returns | Description |
|---|---|---|
layers() |
list[Layer] |
Ordered list of image layers (base → top) |
audit() |
list[AuditResult] |
Best-practice audit findings |
diff(other) |
list[DiffEntry] |
Filesystem differences vs. another image |
report() |
ImageReport |
Combined layers + audit, serializable to JSON |
print_layers() |
None |
Pretty-print layer table to terminal |
print_audit() |
None |
Pretty-print audit results to terminal |
print_diff(other) |
None |
Pretty-print filesystem diff to terminal |
Data Classes
Layer—index,digest,size_bytes,command,created_at,size_human(property)AuditResult—rule_id,severity,message,layer_indexDiffEntry—path,change_type,size_before,size_afterImageReport—image_name,image_id,total_size_bytes,layers,audit_results,to_dict(),to_json()
Exceptions
DockerLensError— base exceptionDockerNotAvailable— Docker daemon unreachableImageNotFound— image not present locallyRemoteRegistryError— network or registry error when fetching via--remote
Audit Rules
| Rule ID | Severity | Description |
|---|---|---|
NO_USER |
WARNING | Container runs as root — no USER instruction found |
APT_CACHE_NOT_CLEARED |
WARNING | apt-get install without cache cleanup in the same layer |
LATEST_TAG |
INFO | Image uses the :latest tag (non-reproducible builds) |
LARGE_LAYER |
INFO | A single layer exceeds 200 MB |
ADD_INSTEAD_OF_COPY |
INFO | ADD used instead of COPY (implicit tar extraction / URL fetch) |
SECRET_PATTERN |
ERROR | Environment variable name matches PASSWORD, SECRET, API_KEY, or TOKEN |
MANY_LAYERS |
INFO | Image has more than 20 layers |
CURL_BASH_PATTERN |
WARNING | curl or wget piped to bash/sh |
EXPOSED_SSH_PORT |
WARNING | SSH port 22 is exposed |
APK_NO_CACHE |
WARNING | apk add used without --no-cache |
PIP_NO_CACHE_DIR |
WARNING | pip install used without --no-cache-dir |
CI/CD Integration (GitHub Actions)
You can easily integrate dockerlens into your CI pipelines to generate Markdown step summaries.
jobs:
analyze-image:
runs-on: ubuntu-latest
steps:
- name: Install dockerlens
run: pip install dockerlens-py
- name: Analyze Image
run: dockerlens analyze my-app:latest --format markdown >> $GITHUB_STEP_SUMMARY
JSON Output
report = ImageAnalyzer("nginx:latest").report()
print(report.to_json())
{
"image_name": "nginx:latest",
"image_id": "sha256:abc123...",
"total_size_bytes": 142000000,
"layers": [
{
"index": 0,
"digest": "sha256:a3ed...",
"size_bytes": 80000000,
"command": "ADD file:abc in /",
"created_at": "2024-11-14T22:13:20+00:00"
}
],
"audit_results": [
{
"rule_id": "NO_USER",
"severity": "WARNING",
"message": "Container runs as root (no USER instruction found)",
"layer_index": null
}
]
}
Contributing
See CONTRIBUTING.md for development setup, testing, and code style guidelines.
License
MIT — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dockerlens_py-0.2.0.tar.gz.
File metadata
- Download URL: dockerlens_py-0.2.0.tar.gz
- Upload date:
- Size: 24.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b93aaf16b48fa9e4f220d5fe7645210587f14449a6691aed2b4cff8d86208f7
|
|
| MD5 |
0289305c539b064fb59946253d01cf87
|
|
| BLAKE2b-256 |
b7a15d446279abe057184dcb12c1f9e966238d1a91a79ce490e6f83c3ee28811
|
Provenance
The following attestation bundles were made for dockerlens_py-0.2.0.tar.gz:
Publisher:
publish.yml on tinkerera/dockerlens
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dockerlens_py-0.2.0.tar.gz -
Subject digest:
0b93aaf16b48fa9e4f220d5fe7645210587f14449a6691aed2b4cff8d86208f7 - Sigstore transparency entry: 1624885031
- Sigstore integration time:
-
Permalink:
tinkerera/dockerlens@2aadbaa7e60e9097d05fda234082e7475ef24aa3 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/tinkerera
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2aadbaa7e60e9097d05fda234082e7475ef24aa3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dockerlens_py-0.2.0-py3-none-any.whl.
File metadata
- Download URL: dockerlens_py-0.2.0-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5970098aecb42301cefac22e1920c7154225d6f3625f3f1bf5c0a48de86f3bd2
|
|
| MD5 |
02f08f034333258e54bfbc470be4a019
|
|
| BLAKE2b-256 |
5a8b2fa8784c14a10553b76fb6e380a5a7eb5919d8f6548f53d8ceea0d2ea122
|
Provenance
The following attestation bundles were made for dockerlens_py-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on tinkerera/dockerlens
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dockerlens_py-0.2.0-py3-none-any.whl -
Subject digest:
5970098aecb42301cefac22e1920c7154225d6f3625f3f1bf5c0a48de86f3bd2 - Sigstore transparency entry: 1624885095
- Sigstore integration time:
-
Permalink:
tinkerera/dockerlens@2aadbaa7e60e9097d05fda234082e7475ef24aa3 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/tinkerera
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2aadbaa7e60e9097d05fda234082e7475ef24aa3 -
Trigger Event:
push
-
Statement type: