DockerDoctor — shipping container as medical kit with stethoscope and diagnostic panels
50 Checks · 11 Categories · Auto-Fix

Diagnose & Fix Docker
Problems Automatically

Interactive CLI that lints your Dockerfile, compose file, and running containers. Get actionable fixes, not just warnings.

Features

Everything you need to lint, diagnose, and fix Docker configurations — from static file checks to live container analysis.

🔍

50 Checks

25 static checks for Dockerfiles, compose files, secrets, line endings, and .dockerignore. 25 runtime checks for builds, startup, networking, performance, images, and cleanup.

🔧

Auto-Fix

Safe fixes applied automatically with --fix or via interactive prompts. Manual fixes include paste-ready code examples.

🖥️

Interactive TUI

Split-pane terminal UI to browse results by severity, view fix details with YAML syntax highlighting, and copy code to clipboard.

📋

Clipboard Copy

Press c in the TUI to extract and copy only the code blocks from fix instructions — properly dedented, ready to paste.

🔎

Smart Discovery

Auto-detects compose files by standard names or content sniffing. Non-standard filenames like infra.yml are found automatically.

CI-Friendly

JSON output, deterministic exit codes, zero interactive prompts. Drop --ci into your GitHub Actions workflow.

Quick Start

1

Install

npm install -g dockerdoctor

Or use without installing:

npx dockerdoctor
2

Run

# Launch interactive mode (default)
dockerdoctor

# Lint just the Dockerfile
dockerdoctor dockerfile

# Check a specific compose file
dockerdoctor compose -c docker-compose.prod.yml

# JSON output for CI
dockerdoctor --json --severity error

# Auto-apply all safe fixes
dockerdoctor --fix
3

Fix

Browse results in the TUI, read fix instructions with YAML highlighting, press c to copy code, and paste directly into your files.

Interactive Mode

Running dockerdoctor with no flags launches interactive mode — a guided wizard that walks you through scanning.

Scan Target

  • Scan current directory — check CWD for Docker files
  • Scan subdirectories — recursively find Docker projects up to 4 levels deep
  • Specify a directory path — enter any custom path
  • Docker daemon only — skip file scanning, check running containers and images

Check Selection

Pick All checks or select specific categories: Dockerfile, Compose, Secrets, Line Endings, Dockerignore, Build, Startup, Network, Performance, Image, or Cleanup.

Subdirectory scanning automatically skips node_modules, .git, dist, build, .next, __pycache__, and vendor.

TUI Browser

When results are found, the TUI shows a split-pane view with severity categories on the left and full detail on the right.

 Browse Results 
Dir: /app   Scan: All checks
────────────────────┬────────────────────────────────────
▸ x Errors (3) Errors
! Warnings (5) 3 issues
i Info (2)
x Service "web" has no healthcheck
x Undefined network "backend"
x Hardcoded secret in ENV
────────────────────┴────────────────────────────────────
↑↓ Navigate Enter: Open q: Exit

Keyboard Shortcuts

/ or j / kNavigate results
Enter or Open category / view detail
or qGo back
Shift+ / Shift+Scroll detail pane
cCopy fix code to clipboard
Ctrl+CExit

The c key extracts only code blocks from fix instructions — dedented and ready to paste directly into your Dockerfile or compose file.

Commands & Flags

Subcommands

dockerdoctor

Launch interactive mode (default)

dockerdoctor check

Run all checks (default with --json/--ci/--fix)

dockerdoctor dockerfile

Lint Dockerfile only — 9 checks

dockerdoctor compose

Lint compose file only — 7 checks

dockerdoctor secrets

Scan for hardcoded secrets — 4 checks

dockerdoctor lineendings

Check for CRLF issues — 3 checks

dockerdoctor build

Diagnose build failures — 4 checks (Docker)

dockerdoctor startup

Diagnose startup failures — 4 checks (Docker)

dockerdoctor network

Diagnose networking issues — 4 checks (Docker)

dockerdoctor perf

Diagnose performance issues — 4 checks (Docker)

dockerdoctor image

Analyze image for bloat — 4 checks (Docker)

dockerdoctor cleanup

Find reclaimable disk space — 5 checks (Docker)

Flags

FlagDescription
--jsonOutput results as JSON
--ciCI mode (JSON output + exit codes)
--fixAuto-apply all safe fixes
--severity <level>Minimum severity: error, warning, or info
-f, --file <path>Path to Dockerfile
-c, --composefile <path>Path to compose file
-V, --versionPrint version
-h, --helpPrint help

Static Checks No Docker Required

25 checks that analyze your files without needing a running Docker daemon.

Dockerfile — 9 checks

CheckWhat it catches
Base image :latestNon-deterministic builds from unpinned base image tags
Running as rootContainer processes running as root user
Shell form CMDShell form instead of exec form for CMD/ENTRYPOINT
Layer orderingCOPY . . before package file copy invalidates cache
npm installUsing npm install instead of npm ci
Missing multi-stageSingle-stage builds that include build tools in the final image
NODE_ENV trapNODE_ENV set before npm ci blocks devDependencies
Missing CHOWNCOPY/ADD without --chown leaves files owned by root
Alpine cacheMissing --no-cache or rm -rf /var/cache/apk/*

Compose — 7 checks

CheckWhat it catches
Missing healthcheckServices with ports but no healthcheck block
Undefined networkService references a network not in the top-level networks block
Network mismatchServices that need to communicate are on different networks
Static IPHardcoded IP addresses in service network configuration
Bind mountsHost-path bind mounts that break portability
Bridge networkUsing the default bridge network instead of custom networks
Swarm ignoredSwarm-specific config (deploy) ignored in docker compose

Secrets — 4 checks

CheckWhat it catches
Dockerfile ENVHardcoded passwords/tokens in ENV instructions
Dockerfile ARGSecrets passed via ARG (visible in image history)
Compose environmentHardcoded secrets in compose service environment
Sensitive COPYCopying .env, key files, or credentials into the image

Line Endings — 3 checks

CheckWhat it catches
CRLF detectionWindows line endings that break shell scripts in Linux containers
Missing .gitattributesNo .gitattributes to enforce consistent line endings
Missing dos2unixNo dos2unix conversion step in the Dockerfile

Dockerignore — 2 checks

CheckWhat it catches
Missing fileNo .dockerignore file, causing bloated build context
Missing entriesCommon entries like node_modules, .git not excluded

Runtime Checks Requires Docker

25 checks that inspect your running Docker daemon, containers, and images.

Build — 4 checks

CheckWhat it catches
Large build contextBuild context too large, slowing down builds
DNS resolutionDNS failures during build (can't download packages)
Disk spaceInsufficient disk space to complete a build
Platform mismatchBuilding for wrong platform (e.g., ARM on x86)

Startup — 4 checks

CheckWhat it catches
Exit code analysisDecodes exit codes (137=OOM, 126=permission, 127=not found)
OOM killedContainers killed by the OOM killer
Environment variablesMissing or empty required environment variables
Entrypoint existsCMD/ENTRYPOINT binary not found or not executable

Network — 4 checks

CheckWhat it catches
Same networkContainers that should communicate are on different networks
DNS resolutionDNS resolution failures between containers
Port conflictsMultiple containers trying to bind the same host port
Localhost bindingServices bound to 127.0.0.1, unreachable from other containers

Performance — 4 checks

CheckWhat it catches
Resource usageHigh CPU or memory consumption
Bind mount I/OSlow I/O from host-mounted volumes
Build cacheDocker build cache not being utilized effectively
Resource limitsNo memory/CPU limits set, risking resource exhaustion

Image — 4 checks

CheckWhat it catches
Image sizeOversized images that waste bandwidth and storage
Layer analysisInefficient layer structure, duplicate content
Architecture mismatchRunning ARM images on x86 or vice versa (via emulation)
Base image bloatBase image includes unnecessary tools and libraries

Cleanup — 5 checks

CheckWhat it catches
Disk usageDocker consuming excessive disk space
Dangling imagesUntagged images left behind by builds
Stopped containersExited containers wasting disk space
Unused volumesVolumes no longer attached to any container
Build cacheBuild cache consuming significant disk space

Compose Discovery

dockerdoctor automatically finds compose files using a two-pass strategy:

1

Standard names

Checks for docker-compose.yml, docker-compose.yaml, compose.yml, and compose.yaml.

2

Content sniffing

If no standard file is found, scans all .yml / .yaml files for a services: key. This catches non-standard filenames like infra.yml or stack.yaml.

Automatically skips CI configs (.gitlab-ci.yml, azure-pipelines.yml), Kubernetes manifests (Chart.yaml, values.yaml), and build tool files (mkdocs.yml, pnpm-lock.yaml).

CI/CD Integration

GitHub Actions

- name: Lint Dockerfiles
  run: npx dockerdoctor --ci --severity error

The --ci flag outputs JSON and uses exit codes:

  • Exit 0 — no errors found
  • Exit 1 — errors found (warnings and info alone don't trigger failure)
  • Exit 2 — invalid arguments (bad file path, invalid severity)

Programmatic API

Import and run checks from your own scripts:

import { buildContext, runChecks } from 'dockerdoctor';

const context = await buildContext(process.cwd());
const report = await runChecks(context, {
  categories: ['dockerfile', 'secrets'],
  minSeverity: 'warning',
});

console.log(`Found ${report.summary.errors} errors`);
for (const result of report.results) {
  console.log(`[${result.severity}] ${result.title}: ${result.message}`);
}

Exports

FunctionDescription
buildContext(cwd)Auto-detect and parse Docker files in a directory
runChecks(context, opts)Execute checks and return a Report
registerCheck(check)Register a custom check
getAllChecks()Get all registered checks
getChecksByCategory(cat)Get checks for a specific category
parseDockerfile(raw, path)Parse a Dockerfile string into structured data
parseCompose(raw, path)Parse a compose file string
findComposeFile(dir)Find a compose file using standard names + sniffing