PureDevTools

Dockerfile Generator

Generate production-ready Dockerfiles for Node.js, Python, Go, Java, Nginx, and more — with presets, live preview, and one-click copy

All processing happens in your browser. No data is sent to any server.

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.

COPY
RUN
COPY

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 FamilySizeUse Case
*:alpine~5 MBMinimal footprint, most workloads
*:slim~30–80 MBDebian-based but stripped down
ubuntu:22.04~77 MBFull Debian environment, broad compatibility
scratch0 MBStatically 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:

CMDENTRYPOINT
Overridable at runtimeYes (docker run image cmd)Only with --entrypoint
Provides defaultsYesYes
Typical useDefault command or argumentsFixed 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:


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

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.

Related Tools

More Code & Config Generators