diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..1a97502fd --- /dev/null +++ b/.dockerignore @@ -0,0 +1,23 @@ +node_modules +.next +out +standalone + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +.env* +!.env.example + +.git +.gitignore + +.DS_Store +*.swp +.idea +.vscode + +coverage +.cache diff --git a/Dockerfile.local b/Dockerfile.local new file mode 100644 index 000000000..016a0be9e --- /dev/null +++ b/Dockerfile.local @@ -0,0 +1,21 @@ +FROM node:20-bookworm-slim +WORKDIR /app + +# Copy package files first for better layer caching +COPY package*.json ./ +RUN npm install + +# Copy source code +COPY . . + +# Set development environment +ENV NODE_ENV=development + +# Copy entrypoint script +COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +EXPOSE 3000 + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/README.md b/README.md index a18de5f09..7bd7973c0 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,57 @@ Visit `http://localhost:3000` and start chatting. Use the prompts on the start s npm run build ``` +### Run with Docker + +Build the production image and run it locally: + +```bash +docker build -t chatkit-app . +docker run --rm -p 3000:3000 --env-file .env.local chatkit-app +``` + +Or pass env vars explicitly: + +```bash +docker run --rm -p 3000:3000 \ + -e OPENAI_API_KEY="..." \ + -e NEXT_PUBLIC_CHATKIT_WORKFLOW_ID="wf_..." \ + chatkit-app +``` + +Visit `http://localhost:3000`. + +### Mount env file, then start service + +If you prefer mounting `.env.local` rather than passing `--env-file`, the image has an entrypoint that reads `/app/.env.local` before starting: + +```bash +docker run --rm -p 3000:3000 \ + -v $(pwd)/.env.local:/app/.env.local:ro \ + chatkit-app +``` + +### Develop inside Docker (hot reload) + +Use the local development setup with bind mounts and your local env: + +```bash +# Create your environment file +cp .env.example .env.local +# Edit .env.local with your OPENAI_API_KEY and NEXT_PUBLIC_CHATKIT_WORKFLOW_ID + +# Start the development container +docker-compose -f docker-compose.local.yml down +docker-compose -f docker-compose.local.yml up --build +``` + +This runs `npm run dev` in a container with: +- Hot reload enabled (source code mounted from host) +- DNS configured for external API access +- Port 3000 exposed to host +- Environment variables loaded from `.env.local` + +Visit `http://localhost:3000` and start chatting. Your code changes will trigger hot reload inside the container. Before deploying your app, you need to verify the domain by adding it to the [Domain allowlist](https://platform.openai.com/settings/organization/security/domain-allowlist) on your dashboard. ## Customization Tips diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 000000000..6ea592ecf --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,26 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile.local + container_name: nextjs-dev + ports: + - "3000:3000" + env_file: + - .env.local + volumes: + - .:/app + - /app/node_modules + - /app/.next + environment: + - NODE_ENV=development + # Ensure Node.js can resolve external APIs + - NODE_TLS_REJECT_UNAUTHORIZED=0 # Only for dev if SSL issues + dns: + - 8.8.8.8 + - 8.8.4.4 + # Add this to use host network stack (best for local dev) + network_mode: bridge + stdin_open: true + tty: true + restart: unless-stopped \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 000000000..045f4e321 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -e + +# Load env variables from a mounted .env.local if present +if [ -f "/app/.env.local" ]; then + export $(grep -E '^[A-Za-z_][A-Za-z0-9_]*=' /app/.env.local | xargs) + echo "✓ Loaded environment variables from .env.local" +fi + +# Validate required environment variables +if [ -z "$OPENAI_API_KEY" ]; then + echo "ERROR: OPENAI_API_KEY is not set" + echo "Make sure it's defined in .env.local" + exit 1 +fi + +if [ -z "$NEXT_PUBLIC_CHATKIT_WORKFLOW_ID" ]; then + echo "ERROR: NEXT_PUBLIC_CHATKIT_WORKFLOW_ID is not set" + echo "Make sure it's defined in .env.local" + exit 1 +fi + +echo "✓ All required environment variables are validated" + +exec "$@" \ No newline at end of file