diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..408987486 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +# VCS +.git +.gitignore + +# Dependencies +node_modules +**/node_modules +.pnpm-store + +# Build outputs and caches +.next +**/.next +dist +build +out +.turbo +.cache +coverage + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Environment files +.env +.env.* +!.env.example + +# Editor and OS files +.vscode +.idea +.DS_Store +Thumbs.db diff --git a/examples/openui-chat/.dockerignore b/examples/openui-chat/.dockerignore new file mode 100644 index 000000000..999ffc10a --- /dev/null +++ b/examples/openui-chat/.dockerignore @@ -0,0 +1,39 @@ +# Node +node_modules +.pnpm-store +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Next.js +.next +out + +# Git +.git +.gitignore + +# Logs +logs +*.log + +# Env files +.env +.env.* +!.env.example + +# OS files +.DS_Store +Thumbs.db + +# Build / cache +dist +build +.turbo +.cache +coverage + +# Editor +.vscode +.idea \ No newline at end of file diff --git a/examples/openui-chat/Dockerfile b/examples/openui-chat/Dockerfile new file mode 100644 index 000000000..b3a36dfe1 --- /dev/null +++ b/examples/openui-chat/Dockerfile @@ -0,0 +1,73 @@ +# syntax=docker/dockerfile:1.7 +# -------------------------------------------------- +# Build stage +# -------------------------------------------------- +FROM node:20-alpine AS builder + +WORKDIR /app + +RUN apk add --no-cache libc6-compat +ARG PNPM_VERSION=9.12.0 +RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate + +ENV NEXT_TELEMETRY_DISABLED=1 + +COPY pnpm-workspace.yaml package.json pnpm-lock.yaml tsconfig.json ./ + +COPY packages/openui-cli/package.json ./packages/openui-cli/ +COPY packages/react-ui/package.json ./packages/react-ui/ +COPY packages/react-headless/package.json ./packages/react-headless/ +COPY packages/react-lang/package.json ./packages/react-lang/ +COPY examples/openui-chat/package.json ./examples/openui-chat/ + +RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile --ignore-scripts + +COPY packages/openui-cli ./packages/openui-cli +COPY packages/react-ui ./packages/react-ui +COPY packages/react-headless ./packages/react-headless +COPY packages/react-lang ./packages/react-lang +COPY examples/openui-chat ./examples/openui-chat + +RUN pnpm --filter @openuidev/cli build +RUN pnpm --filter @openuidev/react-ui build +RUN pnpm --filter @openuidev/react-headless build +RUN pnpm --filter @openuidev/react-lang build + +WORKDIR /app/examples/openui-chat +RUN node /app/packages/openui-cli/dist/index.js generate src/library.ts --out src/generated/system-prompt.txt \ + && pnpm build + + + +# -------------------------------------------------- +# Runtime stage +# -------------------------------------------------- +FROM node:20-alpine AS runner + +WORKDIR /app + +RUN apk add --no-cache libc6-compat + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 HOSTNAME=0.0.0.0 + +RUN addgroup -S nodejs && adduser -S nextjs -G nodejs +USER nextjs + +# Copy full standalone output to avoid brittle partial-copy assumptions +COPY --from=builder --chown=nextjs:nodejs /app/examples/openui-chat/.next/standalone ./ + +# Static assets expected by Next at runtime +COPY --from=builder --chown=nextjs:nodejs /app/examples/openui-chat/.next/static ./examples/openui-chat/.next/static + +# If your app has a public directory, include this line +# COPY --from=builder --chown=nextjs:nodejs /app/examples/openui-chat/public ./examples/openui-chat/public + +EXPOSE 3000 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD node -e "fetch('http://127.0.0.1:3000').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" + +CMD ["node", "examples/openui-chat/server.js"] \ No newline at end of file diff --git a/examples/openui-chat/README.md b/examples/openui-chat/README.md index 03a161d8b..94267107d 100644 --- a/examples/openui-chat/README.md +++ b/examples/openui-chat/README.md @@ -25,3 +25,30 @@ To learn more about OpenUI, take a look at the following resources: - [OpenUI Documentation](https://openui.com/docs) - learn about OpenUI features and API. - [OpenUI GitHub repository](https://github.com/thesysdev/openui) - your feedback and contributions are welcome! + +## Docker Usage + +You can build the image either from the example directory or from the repository root. + +### Option 1: From examples/openui-chat + +```bash +cd examples/openui-chat +docker build -f Dockerfile -t openui-chat ../.. +docker run --rm -p 3000:3000 -e OPENAI_API_KEY=your_api_key openui-chat +``` + +### Option 2: From repository root + +```bash +docker build -f examples/openui-chat/Dockerfile -t openui-chat . +docker run --rm -p 3000:3000 -e OPENAI_API_KEY=your_api_key openui-chat +``` + +⚠️ The build context must be the repository root (either `.` or `../..`) because this example depends on pnpm workspace packages. + +Notes: + +- The Docker build uses pnpm workspace dependencies from the monorepo. +- Runtime uses Next.js standalone output (`node examples/openui-chat/server.js`). +- A placeholder API key will start the app, but chat requests will return `401`. diff --git a/examples/openui-chat/next.config.ts b/examples/openui-chat/next.config.ts index 69512fdcd..d6663987d 100644 --- a/examples/openui-chat/next.config.ts +++ b/examples/openui-chat/next.config.ts @@ -1,6 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { + output: "standalone", turbopack: {}, transpilePackages: ["@openuidev/react-ui", "@openuidev/react-headless", "@openuidev/react-lang"], };