How the Docker Setup Works for the AI Website Cloner: Multi-Stage Build Explained

The AI website cloner uses a multi-stage Dockerfile for optimized production builds and a lightweight Alpine-based Dockerfile.dev for development with hot reload support.

The JCodesMore/ai-website-cloner-template repository containerizes a Next.js application using Docker to ensure consistent environments across development and production. Understanding the Docker setup for the AI website cloner helps you deploy efficiently while maintaining security best practices and minimal image sizes.

Production Architecture: The Multi-Stage Dockerfile

The production image defined in Dockerfile implements a three-stage build process that separates dependency installation, compilation, and runtime into distinct layers. This approach minimizes the final image size by excluding build tools and source code from the deployment artifact.

Stage 1 – Dependency Caching (dependencies)

The first stage uses node:${NODE_VERSION} (defaulting to 24.14.1-slim) as its base. This stage installs project dependencies once and caches them for subsequent builds.

Key implementation details in Dockerfile:

  • Sets working directory to /app
  • Copies lockfiles (package.json, yarn.lock*, package-lock.json*, pnpm-lock.yaml*, .npmrc*)
  • Executes an installation command that detects the appropriate package manager based on the lockfile present
  • Utilizes Docker cache mounts for /root/.npm, /usr/local/share/.cache/yarn, and /root/.local/share/pnpm/store to speed up rebuilds

# From Dockerfile - Stage 1 excerpt

RUN --mount=type=cache,target=/root/.npm \
    --mount=type=cache,target=/usr/local/share/.cache/yarn \
    --mount=type=cache,target=/root/.local/share/pnpm/store \
    npm install

Stage 2 – Application Build (builder)

The builder stage compiles the Next.js application in standalone mode, which outputs a self-contained server bundle.

This stage copies node_modules from the dependencies stage, then copies the full source tree. It sets NODE_ENV=production and executes the build script (npm run build, yarn build, or pnpm build depending on your lockfile).

The standalone output mode generates a .next/standalone directory containing only the essential files needed to run the application, eliminating the need for the full Next.js package in the final image.

Stage 3 – Minimal Runtime (runner)

The final stage produces a secure, minimal image containing only the compiled application. It configures the environment with NODE_ENV=production, PORT=3000, and HOSTNAME="0.0.0.0".

Critical security and configuration steps:

  • Copies only production assets (public folder) and compiled output (.next/standalone and .next/static)
  • Creates a writable .next directory for the prerender cache
  • Changes ownership of the application directory to the non-root node user
  • Switches to the node user before starting the server
  • Exposes port 3000 and launches the server with node server.js

# From Dockerfile - Stage 3 excerpt

USER node
EXPOSE 3000
CMD ["node", "server.js"]

Development Workflow with Dockerfile.dev

For local development, Dockerfile.dev provides a lightweight environment based on node:24-alpine. This configuration prioritizes fast iteration over image size.

The development container:

  • Installs dependencies from package.json and package-lock.json during the image build
  • Exposes port 3000
  • Sets NODE_ENV=development and disables telemetry with NEXT_TELEMETRY_DISABLED=1
  • Expects the source code to be mounted as a volume at runtime, enabling Next.js hot reload without image rebuilds
  • Runs npm run dev as the entry point

# From Dockerfile.dev

FROM node:24-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
ENV NODE_ENV=development
ENV NEXT_TELEMETRY_DISABLED=1
EXPOSE 3000
CMD ["npm", "run", "dev"]

Building and Running the Containers

Use these commands to work with the Docker setup for the AI website cloner:

Production deployment:


# Build the optimized production image

docker build -f Dockerfile -t ai-website-cloner .

# Run the production container

docker run -p 3000:3000 ai-website-cloner

Development with hot reload:


# Build the development image

docker build -f Dockerfile.dev -t ai-website-cloner-dev .

# Run with volume mount for live code changes

docker run -p 3000:3000 -v "$(pwd)":/app ai-website-cloner-dev

The volume mount -v "$(pwd)":/app maps your local repository into the container, allowing the Next.js development server to detect file changes and reload instantly.

Security and Performance Optimizations

The Docker setup for the AI website cloner implements several best practices:

  • Multi-stage builds discard build-time dependencies and source files, reducing the production image attack surface
  • Cache mounts in the dependencies stage dramatically reduce rebuild times when only application code changes
  • Non-root execution via the node user mitigates container escape vulnerabilities
  • Standalone output mode eliminates unnecessary Node.js modules from the runtime environment

Summary

  • The repository uses two separate Dockerfiles: Dockerfile for production and Dockerfile.dev for development
  • Production builds use a three-stage process (dependencies, builder, runner) based on Node 24.14.1-slim
  • Cache mounts for package managers speed up subsequent builds by persisting download caches between runs
  • The production image runs as the non-root node user and serves only the compiled standalone output on port 3000
  • Development uses an Alpine Linux base image with volume mounting to enable hot reload without container rebuilds

Frequently Asked Questions

What base image does the production Dockerfile use?

The production Dockerfile uses node:${NODE_VERSION} with a default of 24.14.1-slim for all three build stages. This slim variant reduces the base image size compared to the full Node image while maintaining compatibility with most npm packages.

How does the development container support hot reloading?

The Dockerfile.dev configures a development environment that expects the source code to be mounted as a volume at runtime using the -v "$(pwd)":/app flag. This mounts your local working directory into the container's /app path, allowing the Next.js development server to detect file changes on your host machine and trigger hot reloads inside the container.

Why does the production image use a multi-stage build?

The multi-stage build separates the dependency installation, compilation, and runtime environments into distinct layers. This approach ensures that the final runner stage contains only the compiled Next.js standalone output and static assets, excluding build tools, source code, and development dependencies. The result is a smaller image with a reduced attack surface and faster deployment times.

What security measures are implemented in the Docker setup?

The production Dockerfile creates a writable .next directory for the prerender cache and changes its ownership to the non-root node user before switching to that user with the USER node directive. This prevents the application from running as root inside the container, following the principle of least privilege and mitigating potential container escape vulnerabilities.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →