Dockerfile Generator
Pick your framework (React, Angular, Vue, Next.js, NestJS, FastAPI, Django, Spring Boot, .NET, PHP and more) and a few options. You get a production-ready Dockerfile with the usual best practices already applied, and a .dockerignore to go with it.
# syntax=docker/dockerfile:1 # 1. Build the site FROM node:24-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # 2. Serve the built files with Nginx FROM nginxinc/nginx-unprivileged:alpine # Sends unknown paths to index.html, so client-side routes work on refresh COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/dist /usr/share/nginx/html EXPOSE 8080
What the generated Dockerfile does
- Multi-stage build where it helps: the first stage has the compilers and dev dependencies, the final image only has what the app needs to run. Images end up several times smaller.
- Dependencies before source code. The lockfile or
requirements.txtis copied and installed first, so Docker reuses that layer until your dependencies change and rebuilds take seconds. - A non-root user. If someone breaks into the app, they don't get root inside the container. Node.js uses the built-in
nodeuser, Go uses a distrolessnonrootimage, .NET uses the image'sappuser, and frontends use the unprivileged Nginx image on port 8080. - Exec-form
CMD(["node", "dist/index.js"]), so your app receives stop signals directly and shuts down cleanly. - An optional health check that Docker uses to mark the container unhealthy when the app stops answering.
React, Angular and Vue: why Nginx
A React, Angular, Vue or Svelte app is just HTML, CSS and JavaScript once it's built, so it doesn't need Node.js in production. The Dockerfile builds it with Node.js in a first stage and copies only the result into a small Nginx image. The extra nginx.conf sends every unknown path to index.html; without it, refreshing a page like /profile returns a 404 because that file doesn't exist on the server, only in the app's router.
Next.js and Nuxt are different: they render pages on the server, so their images run Node.js. For Next.js, add output: "standalone" to next.config first, which makes the image several times smaller.
Build and run it
docker build -t my-app .
docker run --rm -p 3000:3000 my-appChange 3000 to your port. Frontends served by Nginx listen on 8080, and PHP on 80. To run it next to a database, the Docker Compose generator writes the compose file for you.
Why the .dockerignore matters
Everything in the folder is sent to Docker when you build. Without a .dockerignore, that includes node_modules, virtual environments, Git history and your .env file, which makes builds slower and can copy secrets into the image. Keep secrets out of images entirely; see how to use .env files safely.
Choosing a base image
The generator uses the official images: -alpine variants for Node.js, -slim for Python (Alpine can break Python packages that ship compiled wheels), distroless for Go, Temurin JRE for Java, Microsoft's ASP.NET runtime for .NET and php:apache for PHP. Pin the version you tested with, and update it on purpose rather than relying on latest.
Keep learning
- Docker Compose for beginners: run your first multi-container app.
- Docker vs virtual machines: what a container really is.
- Backing up Docker volumes: don't lose your data.