DEV Community

Cover image for I got tired of Googling Docker commands, so I built an interactive cheatsheet
Akash Pattnaik
Akash Pattnaik

Posted on

I got tired of Googling Docker commands, so I built an interactive cheatsheet

Let me paint you a picture.

It's late. You're writing a Dockerfile. You're in the zone — the kind of focus where you're actually moving fast and everything is clicking. You type HEALTHCHECK and your fingers pause.

Is it --interval or --period? And what's the timeout default again? Is there a --start-period flag or did you make that up?

You open a new tab.

You type "dockerfile healthcheck options" into Google.

The first result is a Stack Overflow answer from 2017. The accepted answer is wrong. The second answer is right but references a flag that was renamed. You scroll past three more answers, open the official Docker docs, find the right section, get your answer, close five tabs, and try to remember where the hell you were.

Three minutes gone. Flow state: destroyed.

I've been doing this for years. And I finally got annoyed enough to do something about it.


What I built

Docker Hub is a free, open-source interactive cheatsheet for all 18 Dockerfile instructions. It lives in your browser, works offline, needs no login, and exists for one reason: so you never have to leave your editor to look up a Docker command again.

Here's the layout — three panels, all visible at once:

┌──────────────┬──────────────────────────┬──────────────┐
│  Cheatsheet  │   Interactive Dockerfile  │  Deep Dive   │
│   + search   │    (hover any keyword)    │  Reference   │
└──────────────┴──────────────────────────┴──────────────┘
Enter fullscreen mode Exit fullscreen mode

Left panel — the cheatsheet

All 18 instructions, grouped by category, with a real-time search bar and category filter pills. Hover any instruction card and you get an instant tooltip summary. Click it and the right panel updates.

Center panel — the interesting part

This is what I actually wanted to exist. It's a realistic, multi-stage Node.js production Dockerfile rendered with token-level syntax highlighting. Every instruction keyword — FROM, RUN, COPY, HEALTHCHECK, all of them — is a hoverable, clickable span.

Hover HEALTHCHECK and you get a popover right there:

  • What it does
  • All its options (--interval, --timeout, --start-period, --retries)
  • A live code example
  • A link to the full reference

No new tab. No context switch.

Right panel — the full reference

Click any keyword and the right panel shows you everything:

  • Full description in readable prose
  • All syntax variants
  • A parameter table (type, required, default, and a BuildKit badge for flags that need it)
  • Multiple copy-ready code examples
  • A layer info strip (creates a layer? persists in image? runtime override flag?)
  • Related instructions you can jump to directly

The tech (keeping it boring on purpose)

This is a Next.js app with Tailwind CSS. That's basically it.

There's no backend. No database. No external API calls. The entire knowledge base is a single well-structured DATA.json file that gets imported at build time.

// lib/data.ts
import data from '../DATA.json'

export function getInstructionById(id: string): Instruction | undefined {
  return data.instructions.find(i => i.id === id)
}

export function searchInstructions(query: string): Instruction[] {
  const q = query.toLowerCase()
  return data.instructions.filter(i =>
    i.name.toLowerCase().includes(q) ||
    i.summary.toLowerCase().includes(q) ||
    i.tags.some(t => t.includes(q))
  )
}
Enter fullscreen mode Exit fullscreen mode

The center panel's syntax highlighting is a custom tokenizer — not Prism, not Shiki, not any heavy library. Just a function that splits each Dockerfile line into typed tokens:

type TokenType = 'keyword' | 'flag' | 'string' | 'comment' | 'path' | 'plain'

interface Token {
  type: TokenType
  value: string
  instructionId?: string  // links keywords to DATA.json
}

function tokenizeLine(line: string): Token[] {
  if (line.trim().startsWith('#')) {
    return [{ type: 'comment', value: line }]
  }
  // first word = keyword if it matches a known instruction
  // --word = flag
  // /word or ./word = path
  // "word" = string
  // everything else = plain
}
Enter fullscreen mode Exit fullscreen mode

Simple, fast, zero dependencies. Perfect for what we need.


The DATA.json schema — the real project

I want to talk about this because it's where most of the work actually went.

Each instruction in the JSON has a full semantic schema:

{
  "id": "healthcheck",
  "name": "HEALTHCHECK",
  "summary": "Defines a command to test container health",
  "description": "Full prose description...",
  "deprecated": false,
  "syntax": [
    "HEALTHCHECK [OPTIONS] CMD <command>",
    "HEALTHCHECK NONE"
  ],
  "layer": {
    "createsLayer": false,
    "persistsInImage": true,
    "overridableAtRuntime": true,
    "runtimeFlag": "--health-cmd, --health-interval"
  },
  "parameters": [
    {
      "name": "--interval",
      "type": "duration",
      "required": false,
      "default": "30s",
      "buildkitOnly": false,
      "description": "Time between health checks"
    }
  ],
  "examples": [
    {
      "id": "healthcheck-http",
      "title": "HTTP endpoint check",
      "description": "Check a health endpoint with curl",
      "code": "HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\\n    CMD curl -f http://localhost:8080/health || exit 1"
    }
  ],
  "relatedInstructions": ["CMD", "ENTRYPOINT", "EXPOSE"],
  "tags": ["health", "monitoring", "check", "liveness"],
  "category": "runtime"
}
Enter fullscreen mode Exit fullscreen mode

This schema is the reason the whole app is easy to contribute to. If you find a wrong example, a missing parameter, or a flag I forgot — you literally just edit the JSON and open a PR. You don't need to understand Next.js, React, or anything about the app. Just find the instruction, fix the data, ship it.

That was an intentional design decision. I wanted the knowledge base to be community-maintained without requiring any contributors to touch application code.


Things I learned building this

1. Token-level interactivity is a surprisingly underused pattern.

Most syntax highlighters treat code as display-only. Making each token interactive — hoverable, clickable, state-driving — forced me to think about the rendering differently. Instead of a <pre> tag, each line is an array of <span> elements with event handlers. Feels obvious in retrospect.

2. A JSON schema is a product decision, not a technical one.

I spent more time thinking about the shape of DATA.json than I did writing component code. Getting the schema right — deciding what fields an Example needs, how parameters should be typed, how to represent the CMD+ENTRYPOINT interaction matrix — was the hard part. The React components were almost mechanical after that.

3. Tooltip positioning is an unsolved problem and I respect Floating UI more now.

My first tooltip implementation overflowed the viewport constantly. The second one flickered. The third one used getBoundingClientRect() + a viewport-edge detection check and finally worked. I should've just used Floating UI from the start.

4. "No backend" is a feature, not a constraint.

Every time I was tempted to add a server route ("for search", "for analytics", "for saving custom Dockerfiles"), I asked myself: can this be done in the client with the static data? The answer was always yes. Keeping it fully static means it deploys anywhere, works offline, and has zero ongoing infrastructure cost.


What's next

A few things I want to add:

  • Custom Dockerfile input — paste your own Dockerfile and get it syntax-highlighted interactively with the same hover system
  • Docker Compose reference — same format, for docker-compose.yml keys
  • BuildKit toggle — hide/show BuildKit-only parameters to reduce noise for people on older Docker versions
  • Print export — a single-page PDF cheatsheet you can pin above your monitor

If any of those sound interesting to you, contributions are very welcome.


Try it / contribute

🐳 Live site: dockerhub
📦 GitHub: github.com/iakashpattnaik/docker_hub

The fastest way to contribute is to open DATA.json, find an instruction you know well, and improve its description, examples, or tags. That alone is enormously valuable.

If you find a bug, spot a wrong parameter, or think an instruction needs a better example — please open an issue or just send a PR directly. The bar is intentionally low.


And if this saves you even one "dockerfile COPY --chown syntax" Google search — that's the whole point.

Happy shipping. 🚀

Top comments (0)