Dockerfile Generator
Generate production-ready Dockerfiles for Node.js, Python, Go, Java, Nginx, and more — with presets, live preview, and one-click copy
Preset
Node.js 20 on Alpine Linux
Base Image
Working Directory
Build Instructions
COPY and RUN instructions in order — drag to reorder is not supported; add them in the sequence you need.
Environment Variables
Exposed Ports
CMD & ENTRYPOINT
Separate arguments with commas or spaces.
Dockerfile
# Generated by PureDevTools Dockerfile Generator # https://puredevtools.tools/dockerfile-generator FROM node:20-alpine ENV NODE_ENV="production" WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["node","server.js"]
You need to containerize a Node.js API. The Dockerfile needs the right Alpine base image, multi-stage build for production, npm ci --omit=dev instead of npm install, a non-root user, proper COPY ordering for layer caching, and HEALTHCHECK. Getting any of these wrong means a 1.2GB image instead of 180MB, or a container that runs as root, or npm rebuilding node_modules on every code change because the COPY order killed the cache.
Why This Generator (Not the Docker Compose Generator)
PureDevTools has a Docker Compose Generator for multi-service orchestration. This tool is for single-container Dockerfiles: pick a preset (Node.js, Python, Go, Java, Nginx), customize base image, packages, env vars, ports, and CMD/ENTRYPOINT, and get a production-ready Dockerfile with best-practice layer ordering. Everything runs in your browser; no data is sent anywhere.
What Is a Dockerfile?
A Dockerfile is a text file that contains a series of instructions for building a Docker image. Docker reads these instructions sequentially to assemble a layered filesystem that becomes your container image. Every instruction — FROM, RUN, COPY, ENV, EXPOSE, CMD — adds a new layer or sets metadata.
Understanding Dockerfile instructions and their correct ordering is the foundation of containerising applications efficiently.
Dockerfile Instructions Reference
FROM — Base Image
Every Dockerfile must begin with a FROM instruction that specifies the starting image:
FROM node:20-alpine
FROM python:3.12-slim
FROM scratch # empty base for statically compiled binaries
Choosing the right base image is one of the most important decisions:
| Base Image Family | Size | Use Case |
|---|---|---|
*:alpine | ~5 MB | Minimal footprint, most workloads |
*:slim | ~30–80 MB | Debian-based but stripped down |
ubuntu:22.04 | ~77 MB | Full Debian environment, broad compatibility |
scratch | 0 MB | Statically compiled Go/Rust binaries |
RUN — Execute Commands
RUN executes commands in a new layer. Best practice: chain related commands with && and clean up caches in the same layer:
# Bad — creates extra layers and leaves cache files
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# Good — single layer, no cache residue
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
COPY — Add Files
COPY copies files from the build context (your local directory) into the image:
COPY package*.json ./ # wildcards are supported
COPY src/ /app/src/
COPY --chown=node:node . . # set file ownership
WORKDIR — Set Working Directory
WORKDIR sets the working directory for subsequent RUN, COPY, CMD, and ENTRYPOINT instructions:
WORKDIR /app
If the directory does not exist, Docker creates it automatically.
ENV — Environment Variables
ENV sets environment variables that persist into the running container:
ENV NODE_ENV="production"
ENV PORT="3000"
ARG — Build-Time Variables
ARG defines variables available only during the build process (not in the running container):
ARG BUILD_VERSION=1.0.0
RUN echo "Building version $BUILD_VERSION"
Override ARGs at build time: docker build --build-arg BUILD_VERSION=2.0.0 .
EXPOSE — Document Ports
EXPOSE documents which port(s) the container listens on at runtime. It does not actually publish ports — use -p when running:
EXPOSE 3000
EXPOSE 8080/tcp
EXPOSE 5353/udp
USER — Set Runtime User
Running containers as root is a security risk. Use USER to switch to a non-root user:
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
ENTRYPOINT vs CMD
Both set what runs when the container starts, but they behave differently:
CMD | ENTRYPOINT | |
|---|---|---|
| Overridable at runtime | Yes (docker run image cmd) | Only with --entrypoint |
| Provides defaults | Yes | Yes |
| Typical use | Default command or arguments | Fixed executable |
# Common pattern: ENTRYPOINT fixes the executable, CMD provides default arguments
ENTRYPOINT ["node"]
CMD ["server.js"] # docker run img → runs: node server.js
# docker run img app.js → runs: node app.js
LABEL — Image Metadata
LABEL adds key-value metadata to an image, useful for CI/CD and image management:
LABEL version="1.0" \
maintainer="team@example.com" \
org.opencontainers.image.source="https://github.com/org/repo"
Exec Form vs Shell Form
Many instructions (RUN, CMD, ENTRYPOINT) support two forms:
# Shell form — runs through /bin/sh -c
CMD node server.js
# Exec form — runs directly (preferred for CMD/ENTRYPOINT)
CMD ["node", "server.js"]
Use exec form for CMD and ENTRYPOINT because:
- Signals (SIGTERM) go directly to your process, not to
/bin/sh - Enables proper graceful shutdown in containers
- Shell form requires a shell to be present in the image
Layer Caching Optimisation
Docker caches each layer. When a layer changes, all subsequent layers are invalidated. Order instructions from least to most frequently changing:
FROM node:20-alpine
# 1. Install dependencies first — changes less often than application code
COPY package*.json ./
RUN npm ci --only=production
# 2. Copy application code — changes frequently
COPY . .
CMD ["node", "server.js"]
If you reverse this order (copy all files first), every code change invalidates the npm ci cache, making builds slower.
Common Presets
Node.js
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV="production"
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Python
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]
Go
FROM golang:1.22-alpine
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .
EXPOSE 8080
CMD ["./main"]
Java (Spring Boot)
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
Nginx Static Site
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY dist/ /usr/share/nginx/html/
EXPOSE 80
Security Best Practices
1. Use Specific Image Tags
# Bad — "latest" can change unexpectedly
FROM node:latest
# Good — pinned to a specific version
FROM node:20.11.0-alpine3.19
2. Run as Non-Root
FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
CMD ["node", "server.js"]
3. Use .dockerignore
Create a .dockerignore file to prevent sensitive files from entering the build context:
node_modules
.env
.git
*.log
coverage/
4. Minimise Image Size
- Use Alpine or slim base images
- Combine
RUNcommands to avoid intermediate layers - Remove package manager caches in the same
RUNlayer
5. Scan for Vulnerabilities
Run docker scout quickview or trivy image myimage to scan for known CVEs in your image layers.
Multi-Stage Builds
Multi-stage builds produce small production images by separating the build environment from the runtime environment:
# Stage 1: Build
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
# Stage 2: Runtime (only the binary, no Go toolchain)
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]
The final image contains only the Alpine base and the compiled binary — no Go compiler, no source code.
FAQ
What is the difference between CMD and ENTRYPOINT?
CMD provides default arguments that can be overridden at docker run time. ENTRYPOINT defines the fixed executable that always runs. When used together, ENTRYPOINT is the command and CMD is the default argument list. Override CMD with: docker run myimage --flag.
Should I use exec form or shell form for CMD?
Use exec form (CMD ["node", "server.js"]) for CMD and ENTRYPOINT. Exec form sends signals directly to your process, enabling proper graceful shutdown. Shell form wraps the command in /bin/sh -c, which can cause issues with SIGTERM handling.
What is the difference between COPY and ADD?
COPY copies local files into the image. ADD does the same but also supports tar extraction and URL downloads. Best practice: use COPY unless you explicitly need the extra functionality of ADD, because COPY is more transparent.
Why should I use .dockerignore?
.dockerignore excludes files from the build context sent to the Docker daemon. Without it, node_modules, .git, log files, and secrets can accidentally end up in your image — increasing image size and creating security risks.
How do I reduce Docker image size?
Use a minimal base image (Alpine, slim, or scratch), chain RUN commands to reduce layers, clean package manager caches within the same RUN instruction, and use multi-stage builds to exclude build tools from the final image.
Is my Dockerfile data sent to a server?
No. The Dockerfile Generator runs entirely in your browser. No configuration data, package names, or generated Dockerfiles are sent to any server.