Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tidy-readme-refresh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@docker-doctor/cli": patch
---

README refresh: real scan output demo, accurate rule count (25), CI usage with `--json`/`--score`, and a working programmatic API example
31 changes: 20 additions & 11 deletions apps/web/components/providers/analytics.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { DatabuddyDevtools } from "@databuddy/devtools/react";
import { Databuddy } from "@databuddy/sdk/react";

import { env } from "@/lib/env";

import { PostHog } from "./posthog";

export const Analytics = () => (
<>
<DatabuddyDevtools enabled={process.env.NODE_ENV !== "production"} />
<Databuddy
clientId={process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID}
trackHashChanges
trackAttributes
trackOutgoingLinks
trackInteractions
trackWebVitals
trackErrors
disabled={process.env.NODE_ENV === "development"}
/>
<PostHog />
{env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID && (
<>
<DatabuddyDevtools enabled={process.env.NODE_ENV !== "production"} />
<Databuddy
clientId={env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID}
disabled={process.env.NODE_ENV === "development"}
trackAttributes
trackErrors
trackHashChanges
trackInteractions
trackOutgoingLinks
trackWebVitals
/>
</>
)}
</>
);
22 changes: 22 additions & 0 deletions apps/web/components/providers/posthog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";

import posthog from "posthog-js";
import { useEffect } from "react";

import { env } from "@/lib/env";

export const PostHog = () => {
useEffect(() => {
if (process.env.NODE_ENV !== "production") {
return;
}

posthog.init(env.NEXT_PUBLIC_POSTHOG_KEY, {
api_host: "/ingest",
defaults: "2025-05-24",
ui_host: "https://us.posthog.com",
});
}, []);

return null;
};
18 changes: 18 additions & 0 deletions apps/web/lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const env = createEnv({
client: {
NEXT_PUBLIC_DATABUDDY_CLIENT_ID: z.string().min(1).optional(),
// Public client token — safe in the bundle; override per environment.
NEXT_PUBLIC_POSTHOG_KEY: z
.string()
.startsWith("phc_")
.default("phc_DjoT7pYmeZ5rhi65kHPRVnQUAweAqkfnJsMeVyQG6EvZ"),
},
experimental__runtimeEnv: {
NEXT_PUBLIC_DATABUDDY_CLIENT_ID:
process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID,
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
},
});
13 changes: 13 additions & 0 deletions apps/web/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { createMDX } from "fumadocs-mdx/next";
import type { NextConfig } from "next";

// Validate environment variables at build time.
import "./lib/env";

const withMDX = createMDX();

const nextConfig: NextConfig = {
Expand All @@ -14,7 +17,17 @@ const nextConfig: NextConfig = {
destination: "/llms.mdx/docs/:path*",
source: "/docs/:path*.md",
},
{
destination: "https://us-assets.i.posthog.com/static/:path*",
source: "/ingest/static/:path*",
},
{
destination: "https://us.i.posthog.com/:path*",
source: "/ingest/:path*",
},
],

skipTrailingSlashRedirect: true,
};

export default withMDX(nextConfig);
5 changes: 4 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@base-ui/react": "^1.6.0",
"@databuddy/sdk": "^2.6.0",
"@docker-doctor/core": "workspace:*",
"@t3-oss/env-nextjs": "^0.13.11",
"cnfast": "^0.0.8",
"date-fns": "^4.4.0",
"fumadocs-core": "^16.12.1",
Expand All @@ -23,11 +24,13 @@
"motion": "^12.42.2",
"next": "16.2.11",
"next-themes": "^0.4.6",
"posthog-js": "^1.414.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · socket/low-supply-chain-score (error)

posthog-js@1.414.0 (lowest version "^1.414.0" allows) scored 36/100 on Socket's supply chain axis (minimum 50). This points to risky install-time behavior — install scripts, obfuscated or native code, network/filesystem/shell access, or typosquatting. Other axes — vulnerability 100, maintenance 100, quality 80, license 100.

Fix → Confirm this is the package you meant to install, and prefer a more established, audited alternative; update "posthog-js": "^1.414.0" in package.json. Full report: https://socket.dev/npm/package/posthog-js/overview/1.414.0. If you've reviewed and accepted this package, raise supplyChain.minScore (currently 50) or set supplyChain.severity: "warning".

Docs

"react": "^19.2.8",
"react-dom": "^19.2.8",
"shiki": "^4.3.1",
"sonner": "^2.0.7",
"tw-animate-css": "^1.4.0"
"tw-animate-css": "^1.4.0",
"zod": "^4.4.3"
},
"devDependencies": {
"@databuddy/devtools": "^0.0.1-beta.0",
Expand Down
29 changes: 29 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 65 additions & 5 deletions packages/docker-doctor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

Your Dockerfiles are probably wrong. Docker Doctor finds out why.

Docker Doctor is an opinionated static analysis tool for Dockerfile and Docker Compose files. It scans your project, runs 21+ rules across security, performance, best practices, Compose, and image size — then gives you a health score and fix guidance.
Docker Doctor is an opinionated static analysis tool for Dockerfile and Docker Compose files. It scans your project, runs 25 rules across security, performance, best practices, Compose, and image size — then gives you a health score and fix guidance.

Works with any project that uses Docker.

Expand All @@ -28,6 +28,37 @@ Works with any project that uses Docker.
npx @docker-doctor/cli@latest
```

One scan gives you a category summary and a health score:

```text
All 9 issues

Security › 2 issues
Performance › 2 issues
Best Practices › 3 issues
Compose › 0 issues
Image Size › 2 issues

. 68 / 100 Needs Work ⚠️
.---. ██████████████████████████████████░░░░░░░░░░░░░░░░
( • • )> Docker Doctor
\___/
```

Add `--verbose` and every finding shows the offending line and how to fix it:

```text
⚠ WARN [docker-doctor/order-layers]:7
> 7 │ RUN npm install

Running package installation command 'npm install' after copying
application files (at line 5). This invalidates the cache on any
code changes.
Help: Copy dependency definition files (like package.json, lockfiles)
and run install commands BEFORE copying the rest of the application
source code.
```

### 2. Install for agents

Once you have an audit, install the skill so your coding agent learns the `/docker-doctor` triage workflow and can fix the issues for you:
Expand All @@ -42,12 +73,18 @@ Works with Claude Code, Cursor, Codex, OpenCode, and many more. After an interac

### 3. Run in CI

Docker Doctor walks you through setting up a GitHub Actions workflow after your first scan:
The CLI is non-interactive when stdin isn't a TTY, and two flags make it pipeline-friendly: `--json` emits a machine-readable report, `--score` prints just the numeric score.

```bash
npx @docker-doctor/cli@latest
# Machine-readable report as a build artifact
npx @docker-doctor/cli@latest --json > docker-doctor-report.json

# Fail the build below a minimum health score
test "$(npx @docker-doctor/cli@latest --score)" -ge 75
```

Prefer not to write the workflow yourself? Docker Doctor offers to set up a GitHub Actions workflow for you after your first interactive scan.

### 4. Configure

```ts
Expand Down Expand Up @@ -87,11 +124,34 @@ The label thresholds are unchanged: `>= 90` Excellent, `>= 75` Good, `>= 50` Nee

## API

Everything the CLI does is exported as plain functions, so you can build your own tooling on top:

```ts
import { discoverProject, toJsonReport } from "@docker-doctor/cli";
import type { Diagnostic } from "@docker-doctor/cli";
import { readFile } from "node:fs/promises";

import {
calculateScore,
discoverProject,
parseDockerfile,
runDockerfileRules,
} from "@docker-doctor/cli";

const project = await discoverProject(".");

const file = project.dockerfiles[0];
const instructions = parseDockerfile(await readFile(file, "utf8"));
const diagnostics = runDockerfileRules(
instructions,
file,
project.dockerignores ?? []
);

const { score, label } = calculateScore(diagnostics);
console.log(`${score}/100 (${label})`);
```

Also exported: `parseCompose` and `runComposeRules` for Compose files, `toJsonReport` for the JSON report shape, `defineConfig` and `loadConfig` for configuration, `allRules` and `findRule` for rule metadata, plus the `Diagnostic`, `DockerDoctorConfig`, `RuleCategory`, and `RuleSeverity` types.

## Contributing

[MIT](LICENSE) and [Issues welcome!](https://github.com/PunGrumpy/docker-doctor/issues)