Generate and validate Dockerfiles for Node.js, Python, Java, Go, PHP apps. Multi-stage builds, best practices, security checks. Copy Dockerfile instantly.
Use this free online Dockerfile Generator directly in your browser. No signup required, no data leaves your device. Part of Utilier — a collection of 133+ developer utilities.
What is Dockerfile Generator & Validator?
Dockerfile defines the steps to build a Docker container image — base image, dependencies, application code, environment variables, exposed ports, and startup command. This tool generates Dockerfiles visually for common stacks (Node.js, Python, Java, Go, PHP, Ruby, .NET) with best practices built-in (multi-stage builds, minimal base images, non-root user, layer caching). It validates syntax, checks for security issues (running as root, hardcoded secrets), and suggests optimizations (layer ordering, COPY vs ADD, .dockerignore).
Stack templates: Pre-configured Dockerfiles for Node.js (npm/yarn), Python (pip/poetry), Java (Maven/Gradle), Go (modules), PHP (Composer), .NET, Ruby (Bundler). Select stack and customize.
Multi-stage builds: Separate build and runtime stages. Build stage installs dependencies and compiles code, runtime stage copies only production artifacts. Reduces final image size by 50-90%.
Best practices: Uses minimal base images (alpine, slim), runs as non-root user, orders layers for caching (dependencies before code), uses COPY instead of ADD, sets working directory.
Security checks: Warns about running as root (USER root), hardcoded secrets (ENV PASSWORD=...), using latest tag (unstable), missing .dockerignore (bloated images).
Writing Dockerfiles manually requires knowledge of best practices, layer caching, multi-stage builds, and security. This tool generates optimized Dockerfiles automatically.
Avoid common mistakes: Typos in instructions (RUNS instead of RUN), wrong order (COPY before RUN apt-get), using ADD instead of COPY, running as root. Tool enforces best practices.
Multi-stage build automation: Multi-stage builds are complex (multiple FROM statements, COPY --from=builder). Tool generates multi-stage Dockerfiles automatically for smaller images.
Learn Dockerfile syntax: See how FROM, RUN, COPY, WORKDIR, EXPOSE, CMD, ENTRYPOINT work together. Great for learning Docker image creation.
Security by default: Tool creates non-root user, avoids latest tag, warns about secrets. Prevents common security vulnerabilities.
Save time: No need to reference Docker docs for instruction syntax or best practices. Tool generates production-ready Dockerfiles instantly.
Optimized layer caching: Tool orders layers correctly: dependencies first (cached unless package.json changes), then code (changes frequently). Faster rebuilds.
When to use Dockerfile generator
Use whenever you need to containerize an application with Docker.
Dockerizing Node.js apps (Express, Next.js, React) for production deployment.
Creating Python containers (Flask, Django, FastAPI) with pip or poetry.
Building Java containers (Spring Boot, Maven, Gradle) with multi-stage builds.
Containerizing Go applications with minimal alpine base images.
Packaging PHP apps (Laravel, Symfony) with Apache or Nginx.
Creating .NET containers (ASP.NET Core) with official Microsoft base images.
Learning Dockerfile syntax and best practices by experimenting with different stacks.
Multi-stage builds: Generates multi-stage Dockerfiles automatically. Build stage + runtime stage. Reduces final image size by 50-90%.
Minimal base images: Uses alpine (5-50 MB) or slim (50-150 MB) variants instead of full images (500+ MB). Faster downloads, smaller storage.
Non-root user: Creates USER appuser and runs app as non-root. Prevents privilege escalation vulnerabilities.
Layer caching optimization: Orders layers for maximum cache reuse: COPY package.json → RUN install → COPY . (code changes don't invalidate dependency cache).
Security validation: Warns about running as root, hardcoded secrets (ENV PASSWORD), using :latest tag, missing .dockerignore, exposed sensitive ports.
.dockerignore generation: Suggests .dockerignore patterns (node_modules, .git, *.log) to exclude from build context. Reduces image size and build time.
Common use cases
Node.js app (Express, Next.js): Generate multi-stage Dockerfile with node:20-alpine. Build stage: npm install. Runtime stage: copy node_modules and code. Runs on port 3000.
Python app (Flask, Django): Use python:3.11-slim. Install dependencies with pip (requirements.txt) or poetry. Run as non-root user. EXPOSE 5000 for Flask.
Java app (Spring Boot): Multi-stage with Maven/Gradle. Build stage: compile JAR. Runtime stage: copy JAR and run with java -jar. Uses openjdk:17-alpine.
Go app: Multi-stage: build with golang:1.21, copy binary to scratch or alpine (2-10 MB final image). Go produces static binaries, no runtime needed.
PHP app (Laravel): Use php:8.2-apache or php:8.2-fpm. Install Composer dependencies. COPY code to /var/www/html. EXPOSE 80 for Apache.
Static site (Nginx): Multi-stage: build with node (npm run build), copy dist/ to nginx:alpine. Serves static files. Final image ~20 MB.
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main . FROM scratch
COPY --from=builder /app/main /main
EXPOSE 8080
ENTRYPOINT ["/main"]
Go produces static binary. scratch = empty image (no OS). Final image ~5-10 MB. Fastest, smallest image possible.
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Build stage runs npm run build (React, Vue, etc.), runtime stage serves with Nginx. Final image ~20 MB (nginx:alpine).
Technical reference
Dockerfile instructions and best practices:
FROM
Sets base image. Example: FROM node:20-alpine, FROM python:3.11-slim. Use specific version (not :latest) for reproducibility. Alpine = smallest, slim = small, official = full.
WORKDIR
Sets working directory. Example: WORKDIR /app. All subsequent commands (RUN, COPY, CMD) execute in this directory. Creates dir if it doesn't exist.
COPY vs ADD
COPY: copies files/dirs from build context to image. ADD: same + auto-extracts .tar and supports URLs. Prefer COPY (explicit). Use ADD only for tar extraction.
RUN
Executes command during build. Example: RUN npm install, RUN apt-get update && apt-get install -y curl. Each RUN creates a layer. Chain commands with && to reduce layers.
ENV
Sets environment variables. Example: ENV NODE_ENV=production PORT=3000. Persists in final container. Avoid hardcoding secrets (use Docker secrets or .env at runtime).
EXPOSE
Documents which ports the container listens on. Example: EXPOSE 3000. Does NOT publish ports (use -p flag in docker run). Informational only.
USER
Sets user for RUN, CMD, ENTRYPOINT. Example: USER appuser. Default is root (insecure). Create non-root user for security: RUN adduser -D appuser && USER appuser.
CMD vs ENTRYPOINT
CMD: default command (can be overridden). ENTRYPOINT: fixed command (args appended). Example: ENTRYPOINT ["node"] CMD ["server.js"] → runs node server.js. Use CMD for most cases.
Multi-stage builds
Multiple FROM statements. Example: FROM node:20 AS builder → RUN npm install → FROM node:20-alpine → COPY --from=builder /app /app. Build stage + runtime stage. Smaller final image.
.dockerignore
Excludes files from build context (like .gitignore). Example: node_modules, .git, *.log, .env. Reduces image size and build time. Place in project root.
Common mistakes to avoid
Using :latest tag for base image, causing non-reproducible builds
Why it happens: :latest tag changes over time (node:latest today = node:22, next month = node:23). This breaks builds when base image updates introduce breaking changes. Builds are not reproducible across time or teams. Common for beginners who want 'newest version'.
How to avoid it: Use specific version tags: node:20-alpine, python:3.11-slim, openjdk:17. Pin major version for stability. Update manually when ready, not automatically via :latest.
COPY . before RUN install, invalidating dependency cache on every code change
Why it happens: Dockerfile layers are cached top-to-bottom. If you COPY . (all code) before RUN npm install, every code change invalidates the install cache, so dependencies reinstall every time (slow). Correct order: COPY package.json → RUN install → COPY . (code changes don't invalidate install cache).
How to avoid it: COPY dependency files first (package.json, requirements.txt, pom.xml), RUN install, then COPY . (application code). This maximizes cache reuse. Only reinstall deps when dependency files change.
Running container as root (USER root or no USER), creating security vulnerability
Why it happens: Default user is root. If attacker exploits container, they have root access inside the container (and potentially on host if misconfigured). Running as non-root limits damage. CIS Docker Benchmark requires non-root user.
How to avoid it: Create non-root user: RUN adduser -D appuser (alpine) or RUN useradd -m appuser (debian). Then USER appuser. For official images (node, python), use built-in user: USER node, USER www-data.
Not using .dockerignore, including node_modules, .git, logs in build context
Why it happens: Without .dockerignore, entire project directory (including node_modules, .git, *.log) is sent to Docker daemon as build context. This bloats image size (hundreds of MB), slows builds, and includes sensitive files (.env, .git credentials).
How to avoid it: Create .dockerignore in project root. Add: node_modules, .git, *.log, .env, dist, build, .vscode, .idea. Exclude files you don't need in the image. Similar to .gitignore but for Docker.
Hardcoding secrets in ENV or RUN commands, exposing credentials in image
Why it happens: ENV PASSWORD=secret or RUN echo 'secret' > file persists in image layers. Anyone with image access (docker history, docker inspect) can extract secrets. Common when deploying to production without proper secret management.
How to avoid it: NEVER hardcode secrets in Dockerfile. Use Docker secrets (docker secret create), environment variables at runtime (-e FLAG), or .env files (docker run --env-file). For build-time secrets, use buildkit secrets (RUN --mount=type=secret).
Frequently asked questions
What is a multi-stage build and why use it?
Multi-stage build uses multiple FROM statements. Build stage installs dependencies and compiles code, runtime stage copies only production artifacts. This reduces final image size by 50-90% (excludes build tools, source code, unused dependencies).
What is the difference between CMD and ENTRYPOINT?
CMD sets default command (can be overridden by docker run args). ENTRYPOINT sets fixed command (args are appended). Use CMD for most cases. Use ENTRYPOINT for containers with a single fixed command (e.g., ENTRYPOINT ["node"] CMD ["server.js"]).
Should I use alpine or slim base images?
alpine = smallest (5-50 MB), uses musl libc (some packages incompatible). slim = small (50-150 MB), uses glibc (better compatibility). Use alpine for minimal size, slim if you need glibc or have package compatibility issues.
How do I run the container as a non-root user?
Create user: RUN adduser -D appuser (alpine) or RUN useradd -m appuser (debian). Then USER appuser. For official images (node, python), use built-in user: USER node, USER www-data. Set ownership: RUN chown -R appuser /app.
What should I put in .dockerignore?
Exclude: node_modules, .git, *.log, .env, dist, build, .vscode, .idea, README.md, docker-compose.yml. Include only files needed in the image. Similar to .gitignore but for Docker build context.
How do I optimize layer caching?
Order layers from least to most frequently changed: FROM → WORKDIR → COPY package.json → RUN install → COPY . → CMD. COPY dependency files before code, so code changes don't invalidate install cache.
Can I use environment variables in the Dockerfile?
Yes. ENV sets variables: ENV NODE_ENV=production. Use ${VAR} in subsequent commands: WORKDIR ${APP_DIR}. Avoid hardcoding secrets. For build-time variables, use ARG (ARG VERSION=1.0, RUN echo ${VERSION}).