For the complete documentation index, see llms.txt. Prefer markdown by appending .md to documentation URLs or sending Accept: text/markdown.

Docker

Generate a production-ready Dockerfile with the built-in generator or add the files manually to containerize your TurboStarter app for any environment.

Docker is a popular platform for containerizing applications, making it easy to package your app with all its dependencies for consistent performance across environments. It simplifies development, testing, and deployment.

This guide explains how to containerize your TurboStarter app using Docker. The fastest path is to use the built-in generator, but you can also add the files manually if you prefer full control.

Generate Docker files

Run the Docker generator from the repository root:

pnpm turbo gen docker

It will:

Prefer doing it manually?

Follow the next two steps to add the same files yourself. The generator is only a shortcut for the setup shown below.

Configure Next.js manually

First of all, we need to configure Next.js to output the build files in the standalone format - it's required for the Docker image to work. To do this, we need to add the following to our next.config.ts file:

apps/web/next.config.ts
import type { NextConfig } from "next";

const config: NextConfig = {
  output: "standalone",

  ...
};

Create a Dockerfile manually

Dockerfile is a text file that contains the instructions for building a Docker image. It defines the environment, dependencies, and commands needed to run your app. You can safely copy the following Dockerfile to your project:

apps/web/Dockerfile
FROM node:24-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

FROM base AS pruner
WORKDIR /app
RUN apk add --no-cache libc6-compat
COPY . .
RUN pnpm dlx turbo prune web --docker

FROM base AS builder
WORKDIR /app
RUN apk add --no-cache libc6-compat
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN pnpm install --frozen-lockfile --ignore-scripts --prefer-offline && pnpm store prune
ENV SKIP_ENV_VALIDATION=1 \
    NODE_ENV=production
COPY --from=pruner /app/out/full/ .
RUN pnpm dlx turbo build --filter=web

FROM base AS runner
WORKDIR /app
RUN addgroup -g 1001 -S nodejs && \
    adduser -S web -u 1001 -G nodejs
COPY --from=builder --chown=web:nodejs /app/apps/web/.next/standalone ./
COPY --from=builder --chown=web:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=builder --chown=web:nodejs /app/apps/web/public ./apps/web/public
USER web
EXPOSE 3000
CMD ["node", "apps/web/server.js"]

Feel free to check out our self-hosting guide for more details on how each stage of the Dockerfile works.

And that's all we need! You can now build and run your Docker image to deploy your app anywhere you want in an isolated environment.

Create a .dockerignore manually

If you skipped the generator, add a .dockerignore file in the repository root. This keeps the Docker build context small and prevents local secrets from being copied into the image:

.dockerignore
# Docker
Dockerfile
.dockerignore
**/Dockerfile

# Dependencies
node_modules
**/node_modules
.pnpm-store

# Build outputs
.next
**/.next
.turbo
**/.turbo
dist
**/dist
build
**/build
.cache
**/.cache
.content-collections
**/.content-collections
coverage
**/coverage

# Other apps
apps/mobile
apps/extension

# Native / tooling artifacts
.expo
**/.expo
.wxt
**/.wxt
.wrangler
**/.wrangler
**/*.ipa
**/*.apk
apps/*/ios
apps/*/android

# Git / IDE
.git
.github

# Env & secrets
.env
.env*.local
.dev.vars
.dev.vars.*

# Vercel / Cloudflare local state
.vercel
**/.vercel
.open-next
**/.open-next
.nitro
**/.nitro
.output
**/.output

Run a container

To test if everything works correctly, you can run a container locally with the following commands:

docker build -f ./apps/web/Dockerfile . -t turbostarter
docker run -p 3000:3000 turbostarter

Make sure to also pass all the required environment variables to the container, so your app can start without any issues.

If everything works correctly, you should be able to access your app at http://localhost:3000.

That's it! You can now build and deploy your app as a Docker container to any supported hosting (e.g. Fly.io) or your own VPS.

Using Docker containers is a great way to isolate your app from the host environment, making it easier to deploy and scale. It also simplifies the workflow if you're working with a team, as you can easily share the Docker image with your colleagues and they will run the app in the exact same environment.

How is this guide?

Last updated on

On this page

Ship your startup everywhere. In minutes.Try TurboStarter