# Prompting For A Dockerfile That Is Not 1.2GB

> Name the constraints — multi-stage, non-root, pinned — or you get the naive one.

- **Author:** [Amara Nwosu (@amara_nwosu)](https://www.promptabide.com/amara_nwosu)
- **Published:** 2026-03-25
- **Updated:** 2026-08-22
- **Tags:** `devops`, `docker`, `containers`
- **Views:** 2819
- **Likes:** 88

## Prompt

```
The default generated Dockerfile is `FROM node:latest`, copy everything, npm install, done. It works and it is 1.2GB and it runs as root.

The constraint list that fixes it:

"Write a Dockerfile for a TypeScript Node service.
- Multi-stage: build stage compiles, runtime stage carries only dist + production deps
- Pin the base image by digest, not by tag
- Run as a non-root user; do not create it as UID 1000 if the base already has one
- Copy package files and install before copying source, so the layer caches
- No secrets in build args
- HEALTHCHECK that hits the real readiness endpoint
- .dockerignore covering node_modules, .git, .env, tests"

Same service, 180MB, non-root, and the dependency layer actually caches between builds.

The digest pinning is the one people push back on. Tags move. If you cannot reproduce a build from six months ago, that is why.
```

## Output

*Produced by Claude · claude-sonnet-4.*

```
FROM node:20-alpine@sha256:... AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev

FROM node:20-alpine@sha256:...
USER node
WORKDIR /app
COPY --from=build --chown=node:node /app/dist ./dist
COPY --from=build --chown=node:node /app/node_modules ./node_modules
HEALTHCHECK CMD wget -qO- http://localhost:5000/health || exit 1
CMD ["node", "dist/index.js"]
```

---

Canonical HTML: https://www.promptabide.com/bides/dockerfile-not-1gb-amara-nwosu-4
Agent guide: https://www.promptabide.com/llms.txt · https://www.promptabide.com/agent-instructions.md
Sitemap: https://www.promptabide.com/sitemap.xml
