Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(monorepo): add Docker support docs and update templates for shadcn/ui monorepo #6562

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions apps/www/content/docs/monorepo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,52 @@ turbo.json

By following these requirements, the CLI will be able to install ui components, blocks, libs and hooks to the correct paths and handle imports for you.

## Docker Support

Below is a quick guide to running your shadcn/ui monorepo project in Docker.

### Prerequisites

- **Docker:** Ensure [Docker](https://docker.com) is installed and running.
- **Next.js Configuration:** Update `next.config.mjs` to enable a standalone build:

```js
export default {
output: "standalone",
// other settings
}
```

### Build the Image

From the repository root, run:

```bash
docker build -t shadcn-ui-web -f apps/web/Dockerfile .
```

### Run the Container

To launch the container, run:

```bash
docker run -p 3000:3000 shadcn-ui-web
```

Alternatively, if you are using Docker Compose:

```bash
docker compose up --build -d
```

Then, visit [http://localhost:3000](http://localhost:3000) in your browser.

### Notes

- The Dockerfile is set up as a multi-stage build to ensure a minimal, secure runtime image. You can check out our [Dockerfile](https://github.com/shadcn-ui/ui/blob/main/templates/monorepo-next/apps/web/Dockerfile) for more details.

- For more guidance on using Turbo Repo with Docker, please refer to the [Turbo Repo docs](https://turbo.build/repo/docs/guides/tools/docker).

## Help us improve monorepo support

We're releasing monorepo support in the CLI as **experimental**. Help us improve it by testing it out and sending feedback.
Expand Down
14 changes: 14 additions & 0 deletions templates/monorepo-next/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,17 @@ To use the components in your app, import them from the `ui` package.
```tsx
import { Button } from "@workspace/ui/components/ui/button"
```

## Using Docker

If you want to use Docker for development, you can uncomment the following line in the `next.config.mjs` file:

```mjs
output: "standalone", // Uncomment this line if you use Docker
```

And then run the following command:

```bash
docker compose up --build -d
```
85 changes: 85 additions & 0 deletions templates/monorepo-next/apps/web/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
###############################################################################
# Base Images
###############################################################################
# Use Node.js 20 Alpine for both build and runtime stages.
# - base-build: Includes build dependencies (e.g. libc6-compat) for compiling assets.
# - base-runner: A minimal runtime image without build dependencies.
FROM node:20-alpine AS base-build
# Update APK and install libc6-compat in one layer.
RUN apk update && apk add --no-cache libc6-compat

FROM node:20-alpine AS base-runner

###############################################################################
# Builder Stage
###############################################################################
# Install build tools and prune the monorepo for the web scope.
FROM base-build AS builder
WORKDIR /app

# Install Turbo CLI globally for monorepo task orchestration.
RUN npm install -g turbo

# Copy the entire monorepo into the container.
COPY . .

# Prune the repository for the 'web' package, optimizing for Docker.
RUN turbo prune --scope=web --docker

###############################################################################
# Installer Stage
###############################################################################
# Install Node.js dependencies and build the web application.
FROM base-build AS installer
WORKDIR /app

# Copy pruned project files and the pnpm lockfile from the builder stage.
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml

# Install Corepack, enable it, and prepare pnpm (matching the version in package.json).
RUN npm install -g corepack@latest \
&& corepack enable \
&& corepack prepare [email protected] --activate

# Install dependencies using pnpm with a frozen lockfile.
RUN pnpm install --frozen-lockfile

# Copy the complete pruned project files needed for the build.
COPY --from=builder /app/out/full/ .

# Ensure that the public directory exists for static assets.
RUN mkdir -p /app/apps/web/public

# Build the web application using Turbo, filtering for the 'web' package.
RUN pnpm dlx turbo run build --filter=web

###############################################################################
# Runner Stage (Final Image)
###############################################################################
# Create a minimal runtime environment with only the necessary runtime assets.
FROM base-runner AS runner
WORKDIR /app

# Create a dedicated non-root user for security.
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs

# Switch to the non-root user.
USER nextjs

# Copy configuration files and metadata from the installer stage.
COPY --from=installer /app/apps/web/next.config.mjs .
COPY --from=installer /app/apps/web/package.json .

# Copy the built Next.js server, static assets, and public files.
# The --chown flag sets correct ownership for the non-root user.
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public

# Expose the default Next.js port.
EXPOSE 3000

# Start the Next.js server.
CMD ["node", "apps/web/server.js"]
1 change: 1 addition & 0 deletions templates/monorepo-next/apps/web/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["@workspace/ui"],
// output: "standalone", // Uncomment this line if you use Docker
}

export default nextConfig
17 changes: 17 additions & 0 deletions templates/monorepo-next/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
web:
build:
context: .
dockerfile: ./apps/web/Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
restart: unless-stopped
networks:
- my_network

networks:
my_network:
name: my_network
driver: bridge