diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e7edc6d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +Dockerfile +.dockerignore +node_modules +npm-debug.log +README.md +.next +.git +.gitignore +.vscode +.idea +*.md +.DS_Store +.env*.local +coverage +.vercel + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1009418 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,65 @@ +FROM node:22-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@10.18.3 --activate + +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json pnpm-lock.yaml* ./ +RUN pnpm install --frozen-lockfile + +# Rebuild the source code only when needed +FROM base AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@10.18.3 --activate + +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED=1 + +RUN pnpm build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED=1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 + +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output +ENV HOSTNAME="0.0.0.0" +CMD ["node", "server.js"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4033492 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +.PHONY: help build start stop restart logs clean dev shell rebuild + +# Variables +IMAGE_NAME := toolhive-cloud-ui +IMAGE_TAG := latest +CONTAINER_NAME := toolhive-cloud-ui +PORT := 3000 + +## Show this help message +help: + @echo "Available commands:" + @grep -E '^## ' $(MAKEFILE_LIST) | sed 's/## //' | awk 'NR%2==1{printf "\033[36m%-15s\033[0m ",$$1} NR%2==0{print}' + +## Build the production docker image +build: + @echo "Building ${IMAGE_NAME}:${IMAGE_TAG} Docker image..." + @docker build -t $(IMAGE_NAME):$(IMAGE_TAG) . + +## Start the production docker container +start: + @docker run -d -p $(PORT):$(PORT) --name $(CONTAINER_NAME) $(IMAGE_NAME):$(IMAGE_TAG) + @echo "Container $(CONTAINER_NAME) running at http://localhost:$(PORT)" + +## Stop the production docker container +stop: + @docker stop $(CONTAINER_NAME) > /dev/null 2>&1 || true + @docker rm $(CONTAINER_NAME) > /dev/null 2>&1 || true + @echo "Container $(CONTAINER_NAME) stopped" + +## Restart the production docker container +restart: stop start + +## Show container logs (follow mode) +logs: + docker logs -f $(CONTAINER_NAME) + +## Remove container and image +clean: stop + @docker rmi $(IMAGE_NAME):$(IMAGE_TAG) > /dev/null 2>&1 || true + @echo "Cleanup complete" + +## Run development server locally +dev: + pnpm dev + +## Open shell in running container +shell: + docker exec -it $(CONTAINER_NAME) /bin/sh + +## Clean and rebuild image +rebuild: clean build + @echo "Rebuild complete" + diff --git a/README.md b/README.md index e215bc4..cd01ecc 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,36 @@ You can start editing the page by modifying `app/page.tsx`. The page auto-update This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## Docker + +This project includes Docker support for containerized deployments. + +### Using Makefile (Recommended) + +```bash +# Show all available commands +make help + +# Build Docker image +make build + +# Start container +make start + +# View logs +make logs + +# Stop container +make stop + +# Clean up (remove container and image) +make clean + +# Rebuild from scratch +make rebuild + +The application will be available at [http://localhost:3000](http://localhost:3000). + ## Learn More To learn more about Next.js, take a look at the following resources: diff --git a/next.config.ts b/next.config.ts index 66e1566..30d7f8b 100644 --- a/next.config.ts +++ b/next.config.ts @@ -3,6 +3,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ reactCompiler: true, + output: "standalone", }; export default nextConfig;