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

> Understand the AI website cloner's Docker setup. Learn about multi-stage builds for optimized production and a lightweight Alpine Dockerfile.dev for development with hot reload.

- Repository: [JCodesMore/ai-website-cloner-template](https://github.com/JCodesMore/ai-website-cloner-template)
- Tags: internals
- Published: 2026-07-22

---

**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`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/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

```dockerfile

# 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`

```dockerfile

# 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`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/package.json) and [`package-lock.json`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/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

```dockerfile

# 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:**

```bash

# 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:**

```bash

# 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.