Dockerfile generator
Choose a runtime and get a multi-stage Dockerfile and a .dockerignore that run as a non-root user, pin their base images and cache dependencies, with every line explained. The Dockerfile Linter checks the result right here.
What it does
It writes a Dockerfile and a .dockerignore for five common runtimes, following Docker's own best practices: a build stage and a lean final image, dependencies installed from the lockfile before the source is copied so the cache survives code changes, BuildKit cache mounts that speed up builds without growing the image, base images pinned to a version tag, a non-root user, a HEALTHCHECK, and CMD or ENTRYPOINT in exec form so the process gets stop signals. Every line comes with a comment that says what it does and why, and the result is checked by the Dockerfile Linter on this page.
How it works
- The files are written on this page from typed templates; nothing is sent anywhere and nothing is built or pulled.
- Each runtime offers the versions it supports, pinned to version tags read from the official registries; the defaults are the current long-term lines.
- The output is checked by the Dockerfile Linter's rules with the .dockerignore it comes with, and the findings, normally none, are shown under the files.
- Before the page was published, every runtime and option combination in the generator's tests was built and run on a hello-world app with Docker: it built, ran as a non-root user, reported healthy and stopped on SIGTERM.
What each runtime gets
- Node.js
- node:<version>-alpine, npm ci or pnpm install --frozen-lockfile without dev dependencies in a separate stage, NODE_ENV=production, the image's node user, and a wget health check.
- Python
- python:<version>-slim, a virtual environment built with pip from requirements.txt or with uv from uv.lock, a dedicated user with a fixed uid, and a health check with Python's urllib.
- Go
- golang:<version>-alpine builds a static binary with cached modules; it runs on distroless (nonroot, no shell) or Alpine with a dedicated user and a wget health check.
- Static site
- Built with npm or pnpm on Node.js 24, or copied as is, and served by nginxinc/nginx-unprivileged on port 8080 as uid 101.
- Java (Maven)
- Maven with a full JDK resolves dependencies into a cache and builds the jar; it runs on eclipse-temurin:<version>-jre-alpine as a dedicated user, with the heap sized to the container.
Example
A Node.js service with npm and the defaults, written by the generator with its explanations:
# syntax=docker/dockerfile:1
# The line above must stay first: it makes BuildKit read this file with the
# current Dockerfile syntax, which the cache mounts below need.
# Stage 1 installs the dependencies in node:24-alpine, a version tag rather than
# latest, so a rebuild uses the same Node.js line.
FROM node:24-alpine AS deps
# Work in /app in this stage.
WORKDIR /app
# Only package.json and package-lock.json first: this layer, and the install
# after it, are rebuilt only when the dependencies change.
COPY package.json package-lock.json ./
# Installs exactly what the lockfile says, without devDependencies. The npm
# cache is a BuildKit cache mount, so it speeds up the next build without
# staying in the image.
RUN --mount=type=cache,target=/root/.npm npm ci --omit=dev
# The final image starts again from node:24-alpine, without the build stage's
# caches and tools.
FROM node:24-alpine
# Production mode for Node.js libraries that read NODE_ENV (Express, for
# example, then caches views and hides stack traces).
ENV NODE_ENV=production
# The port the application should listen on. Many frameworks read PORT; if yours
# does not, set the port in its configuration to 3000.
ENV PORT=3000
# The application lives in /app.
WORKDIR /app
# The installed dependencies from stage 1. The package manager and its cache
# stay behind.
COPY --from=deps /app ./
# The source, after the dependencies so a code change does not reinstall them.
# The files stay owned by root, so the application cannot change its own code;
# .dockerignore keeps .git, .env and local builds out.
COPY . .
# The official Node.js image has an unprivileged user, node (uid 1000); the
# process runs as it, not as root.
USER node
# Documents that the application listens on port 3000. It publishes nothing:
# docker run -p or Compose ports: does.
EXPOSE 3000
# Docker marks the container unhealthy when http://127.0.0.1:3000/ stops
# answering. It uses BusyBox wget, which the image already has.
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD ["wget", "-q", "--spider", "http://127.0.0.1:3000/"]
# Starts server.js in exec form: the process is PID 1 and receives SIGTERM on
# docker stop.
CMD ["node", "server.js"]
# Git history: large, and it can hold secrets that were removed from the code.
.git
# Environment files and keys: COPY . . would otherwise put them in the image,
# where anyone who pulls it can read them.
.env
.env.*
*.pem
*.key
# The Docker files themselves: the application does not need them, and a change
# to them would invalidate the source layer.
Dockerfile
.dockerignore
compose*.y*ml
docker-compose*.y*ml
# Logs and editor files.
*.log
.DS_Store
.idea
.vscode
# Dependencies installed on your machine: the image installs its own, for its
# own platform.
node_modules
npm-debug.log*
coverage
The Dockerfile Linter's findings on it:
Findings
0 findings: 0 error, 0 high, 0 medium, 0 low, 0 info.
No findings.
Limits
- It writes the files; it does not build them, and it does not read your repository to detect the runtime or the framework.
- Your project must match what the Dockerfile expects (a lockfile, the file to run, a build script); the notes under the output list it for your choices.
- Tags such as node:24-alpine receive security updates within their version line. To freeze an exact image, add its digest and update it on purpose.
- One service per Dockerfile: monorepos, native build dependencies, private registries and build secrets need changes the generator does not make.
Methodology: how the numbers are worked out
Sources
- Docker Docs: Dockerfile reference
- Docker Docs: Building best practices
- Docker Docs: Build checks
- Docker Docs: Build secrets
- Docker Docs: Build context and .dockerignore
- Docker Docs: Multi-stage builds
- Docker Docs: Optimize cache usage
- Node.js: Release schedule
- Python: Status of Python versions
- Go: Release policy
- uv: Using uv in Docker
- Distroless container images
- nginx: unprivileged image
- Eclipse Temurin: Docker images
Related
Next step
A free public tool by ANAROQ, a company building compute infrastructure. What ANAROQ is building