Choose your stack and options to get a production-ready Dockerfile that follows current best practices: multi-stage builds, cached dependency layers, a non-root user and an optional health check. A matching .dockerignore and the build and run commands are generated too.
Last updated:
Generated files
Advertisement
Advertisement
How to use the Dockerfile Generator
Choose a stack: Node.js, Python, Go or a static site served by nginx.
Pick the version and base image variant (alpine, slim, distroless) and your package manager or dependency file.
Set the app details: working directory, port, start command, environment variables and an optional health check path.
Toggle best practices like multi-stage build, non-root user and BuildKit cache mounts.
Copy or download the Dockerfile and .dockerignore into your project root, then run the docker build command shown.
Dockerfile instructions reference
Instruction
What it does
Tip
FROM image AS name
Starts a build stage from a base image.
Pin a version tag (node:24-alpine), never rely on latest.
WORKDIR /app
Sets (and creates) the working directory for later steps.
Use it instead of RUN cd ….
COPY src dest
Copies files from the build context or, with --from=stage, from another stage.
Add --chown=user:group so a non-root user can write.
RUN command
Runs a command and saves the result as a new layer.
Combine related commands with && to keep layers small.
ENV KEY=value
Sets environment variables for later steps and the running container.
Never bake secrets in; they stay in the image history.
EXPOSE 3000
Documents the port the app listens on.
Publishing still needs -p host:container.
USER name
Runs the following steps and the container as this user.
Put it after steps that need root (package installs).
HEALTHCHECK CMD …
Lets Docker mark the container healthy or unhealthy.
The command must exist in the image (no curl in slim images).
CMD ["exe","arg"]
Default command, replaced by docker run arguments.
Use the JSON exec form so signals reach your app.
ENTRYPOINT ["exe"]
Fixed executable; CMD and run arguments are appended.
Good for single-binary images like Go apps.
Typical image sizes by base
Approximate compressed sizes of the base images on Docker Hub (your app and dependencies come on top). The point is the order of magnitude: choosing the runtime base matters more than almost any other optimisation.
Base image
Approx. size
Good for
gcr.io/distroless/static-debian12
~2 MB
Static Go or Rust binaries
alpine:3.22
~4 MB
Tiny images that still need a shell
nginx:1.28-alpine
~20 MB
Static sites and SPAs
node:24-alpine
~55 MB
Node apps without tricky native modules
python:3.13-slim
~45 MB
Most Python web apps
node:24-slim
~75 MB
Node apps needing glibc
golang:1.26 / node:24 (full)
300 MB+
Build stages only, not the final image
Checklist for a production-ready image
Order layers from least to most frequently changed: base image, system packages, dependency manifests, dependency install, then source code.
Use a lock file and a clean install command (npm ci, pnpm install --frozen-lockfile, pinned requirements.txt) so builds are reproducible.
Keep secrets out of the build context with .dockerignore, and pass them at run time or with RUN --mount=type=secret.
Run as non-root and give that user ownership only of what it must write.
Handle SIGTERM: start your process directly in exec form, or add --init to docker run if your app spawns child processes.
Scan and rebuild regularly (for example with docker scout cves) to pick up security patches in the base image.
Frequently asked questions
What is a multi-stage Docker build?
A Dockerfile with several FROM instructions. Early stages install compilers and dev dependencies and build the app; the final stage starts from a small base image and copies in only the built output. The result is a smaller, safer image without build tools.
Why run the container as a non-root user?
If an attacker breaks into the app, a non-root process has far fewer privileges inside the container and on the host. The official node image includes a node user, distroless images offer a nonroot tag, and for other images the generator creates a dedicated user.
Why copy package.json before the rest of the code?
Docker caches each layer. Copying only the dependency manifests and lock file first means the slow install step is reused from cache until your dependencies change, so code-only changes rebuild in seconds.
Alpine, slim or distroless: which base should I use?
Alpine is the smallest but uses musl libc, which can break some native modules and Python wheels. Debian slim is a safe, compatible default. Distroless images contain only your app and its runtime with no shell or package manager, which is ideal for static Go binaries.
What does .dockerignore do?
It lists files Docker should not send to the build context, such as node_modules, .git, local .env files and build output. That makes builds faster, avoids leaking secrets into images and prevents host-built dependencies from overwriting the ones installed in the container.
Does EXPOSE publish the port?
No. EXPOSE only documents which port the app listens on. You still publish it at run time with docker run -p 8080:3000 or the ports section of docker-compose.
What is the difference between CMD and ENTRYPOINT?
CMD sets the default command, which is replaced by any arguments given to docker run. ENTRYPOINT sets the executable that always runs, and CMD or run arguments are appended to it. Use the JSON exec form so signals like SIGTERM reach your process.
Are all the tools on FreeToolCabin tested for quality and accuracy?
Yes! Every tool on our site undergoes automated Q/A testing in real browser environments to ensure high precision, correct output, and zero errors. If you happen to spot a bug or have a suggestion, please contact us at [email protected] and our team will review it right away.