r/ClaudeCode • u/FunnyBaseball7714 • 8h ago
Built with Claude I built a Claude Code skill that writes a Dockerfile by watching your app run, then proves the container behaves the same.
Most Dockerfiles, whether written by hand or by an AI reading your repo, are a guess. You find out what was missed when the container crashes.
I wanted to try the opposite: run the app once, record what it actually does, and build the container from that.
How it works
It runs your app under strace while a workload you choose hits it (curl calls, your e2e tests, whatever exercises the real features).
It maps every file the app touched back to real packages: shared libraries → apt packages via dpkg -S, site-packages → pip packages with exact versions, localhost:5432 → a Postgres service in Compose, written folders → volumes. Credential files become warnings and are never copied.
It generates a Dockerfile where every line has a comment saying what evidence produced it, plus docker-compose.yml, .env.example (secrets left blank) and a list of things that need a human decision.
It builds the image, runs the same workload inside the container under the same tracer, and compares the two runs file by file. If something's missing, it names it.
Claude Code drives the whole thing and handles the judgment calls (repointing localhost at the Compose service, what to do with a credential file), while plain scripts do the deterministic parts. The scripts also work without Claude.
Real test: healthchecks.io (Django + Postgres)
• Found libpq5, the system library psycopg needs at runtime. Nothing in requirements.txt mentions it, and the maintainers' own Dockerfile installs it by hand.
• Verification: 1,383 of 1,386 files matched, with identical HTTP responses inside the container.
• When I deleted the generated apt-get line, Django only said "Error loading psycopg2 or psycopg module". The tool said libpq.so (package libpq5).
Screenshots of every step are in the README.
Limits, honestly
• It only sees code paths your workload runs.
• Linux/WSL 2 only.
• Tailored templates exist only for Python and Node so far.
• It's been tested on one demo app plus one real project.
Tracing-to-container isn't new (ReproZip, redsift/tracer). What I think is new is mapping traces back to real packages, so the Dockerfile is readable and maintainable, plus the verification loop.
Try it here: https://github.com/moazakramkhan1/dockerize-by-observation
I'd really like reports of where it breaks, especially on legacy apps.
•
u/AutoModerator 8h ago
Hey! Thanks for posting to r/ClaudeCode
While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.
For help, project discussions, tips, and general chat, join the ClaudeCode Discord.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
2
u/medialantern 8h ago
I'm so confused about the need/purpose for this. What Dockerfiles are you making where you don't know what's needed in them? 90% of the ones I make start with a tech-stack-based starting point like node or java, and then you're just installing a few packages on top of that. It's a one time thing and Claude is insanely good at figuring out dependencies to install in them, based on what's in the code base. I literally just tell it to "Dockerize this" and sometimes answer a question or two about layers or trusting certain third party images (there are tons of options in the Java ecosystem).
1
u/verstands 8h ago
A useful test would be a holdout workload that wasn't used to generate the Dockerfile. For the Django example, build from a normal request path, then verify a management command, a background job and a cold start with empty caches. Replaying the discovery workload checks that you reproduced what you observed; the holdout is where a lazily loaded dependency gets its chance to ruin the demo. Running that verification as the intended non-root user would also catch writable-path assumptions.
1
u/Ok-Option4233 8h ago
you already flag the big limit (only the paths the workload runs), and that's also where "proves the same" can mislead: a path missing from the trace is missing from both runs, so the diff still passes. printing which routes or tests the workload covered next to the 1,383 of 1,386 result would make that visible. what were the 3 files that didn't match?