#!/usr/bin/env python3 """Docker system audit: collect container diagnostics and return as JSON.""" import json import os import subprocess def cmd(args, parse_json=False): try: result = subprocess.run( args, capture_output=True, text=True, timeout=30, ) out = (result.stdout + result.stderr).strip() if parse_json: try: return json.loads(out) if out else None except json.JSONDecodeError: return out return out except Exception as e: return f"ERROR: {e}" def read_file(path): try: with open(path) as f: return f.read().strip().splitlines() except FileNotFoundError: return None def main(): audit = {} # Container identity audit["container_id"] = os.environ.get("HOSTNAME") audit["environment"] = dict(os.environ) # OS information inside container audit["os_release"] = read_file("/etc/os-release") audit["uname"] = cmd(["uname", "-a"]) # Installed packages (works for Debian/Ubuntu, Alpine, etc.) audit["packages"] = {} if os.path.exists("/etc/alpine-release"): audit["packages"]["manager"] = "apk" audit["packages"]["installed"] = cmd( ["apk", "info", "-v"] ).splitlines() audit["packages"]["upgradeable"] = cmd( ["apk", "version", "-l", "<"] ).splitlines() elif os.path.exists("/etc/debian_version"): audit["packages"]["manager"] = "dpkg" audit["packages"]["installed"] = cmd( ["dpkg-query", "-W", "-f=${Package}-${Version}\n"] ).splitlines() elif os.path.exists("/etc/redhat-release"): audit["packages"]["manager"] = "rpm" audit["packages"]["installed"] = cmd( ["rpm", "-qa"] ).splitlines() # Docker engine information audit["docker_version"] = cmd( ["docker", "version", "--format", "{{json .}}"], parse_json=True, ) audit["docker_info"] = cmd( ["docker", "info", "--format", "{{json .}}"], parse_json=True, ) # Containers containers = cmd( ["docker", "ps", "-a", "--format", "{{json .}}"], parse_json=True, ) if isinstance(containers, list): audit["docker_containers"] = containers else: audit["docker_containers"] = [] # Images audit["docker_images"] = cmd( ["docker", "images", "--format", "{{json .}}"], parse_json=True, ) # Runtime stats audit["docker_stats"] = cmd( [ "docker", "stats", "--no-stream", "--format", "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}", ] ) # Container logs logs = {} for c in audit["docker_containers"]: name = c.get("Names") or c.get("ID") if not name: continue logs[name] = cmd( [ "docker", "logs", "--tail", "100", name, ] ) audit["docker_logs"] = logs # SSH config if present audit["sshd_config"] = cmd( ["sshd", "-T"] ).splitlines() # Users audit["passwd"] = read_file("/etc/passwd") # Runtime info audit["uptime"] = cmd(["uptime"]) # cgroups (useful in Docker) audit["cgroup"] = read_file("/proc/self/cgroup") # Mounted filesystems audit["mounts"] = cmd(["mount"]).splitlines() print(json.dumps(audit, indent=2)) if __name__ == "__main__": main()