diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..21b6625 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +Dockerfile +.dockerignore +.git +.gitignore +.next +.kiro +.vscode +node_modules +npm-debug.log +README.md +*.md +.env +.env.local +.env.*.local +coverage +.DS_Store +*.pem +tsconfig.tsbuildinfo diff --git a/DOCKER_SETUP.md b/DOCKER_SETUP.md new file mode 100644 index 0000000..bdd9213 --- /dev/null +++ b/DOCKER_SETUP.md @@ -0,0 +1,153 @@ +# Docker Setup Guide + +This guide explains how to run the Ultimate Lists App using Docker on port 3500. + +## Prerequisites + +- Docker and Docker Compose installed +- MySQL server running (external to Docker) +- Environment variables configured + +## Configuration + +### 1. Update next.config.js + +The application needs to be configured for standalone output. Update your `next.config.js`: + +```javascript +const nextConfig = { + output: 'standalone', + // ... rest of your config +} +``` + +### 2. Environment Variables + +Create a `.env` file in the project root with your MySQL connection details: + +```env +# MySQL Connection (external server) +DATABASE_URL="mysql://user:password@host:port/database" + +# For Docker host machine MySQL, use: +# DATABASE_URL="mysql://user:password@host.docker.internal:3306/database" + +# NextAuth Configuration +NEXTAUTH_URL=http://localhost:3500 +NEXTAUTH_SECRET=your-secret-key-here +AUTH_SECRET=your-secret-key-here + +# Optional: MySQL connection check variables +DB_HOST=host.docker.internal +DB_PORT=3306 +DB_USER=your-db-user +DB_PASSWORD=your-db-password +``` + +**Important:** If your MySQL server is running on your host machine (localhost), use `host.docker.internal` instead of `localhost` in the DATABASE_URL. + +### 3. Run Database Migrations + +Before building the Docker image, ensure your database schema is up to date: + +```bash +npm install +npx prisma generate +npx prisma db push +``` + +## Building and Running + +### Option 1: Using Docker Compose (Recommended) + +```bash +# Build and start the container +docker-compose up -d + +# View logs +docker-compose logs -f app + +# Stop the container +docker-compose down +``` + +### Option 2: Using Docker directly + +```bash +# Build the image +docker build -t ultimate-lists-app . + +# Run the container +docker run -d \ + -p 3500:3500 \ + --env-file .env \ + --name ultimate-lists-app \ + ultimate-lists-app + +# View logs +docker logs -f ultimate-lists-app + +# Stop the container +docker stop ultimate-lists-app +docker rm ultimate-lists-app +``` + +## Accessing the Application + +Once running, access the application at: +- **http://localhost:3500** + +## Troubleshooting + +### Cannot connect to MySQL + +If you see database connection errors: + +1. Verify MySQL is running and accessible +2. Check that you're using `host.docker.internal` instead of `localhost` in DATABASE_URL +3. Ensure MySQL allows connections from Docker containers +4. Verify firewall settings allow the connection + +### Build fails + +If the build fails: + +1. Ensure `output: 'standalone'` is set in `next.config.js` +2. Check that all dependencies are properly installed +3. Verify Prisma schema is valid + +### Port already in use + +If port 3500 is already in use: + +```bash +# Find what's using the port +lsof -i :3500 + +# Change the port in docker-compose.yml or use a different port: +docker run -p 3501:3500 ... +``` + +## Development vs Production + +This Docker setup is configured for production use. For development: + +```bash +# Use the regular dev server +npm run dev +``` + +## Updating the Application + +To update after code changes: + +```bash +# Rebuild and restart +docker-compose up -d --build + +# Or with Docker directly +docker build -t ultimate-lists-app . +docker stop ultimate-lists-app +docker rm ultimate-lists-app +docker run -d -p 3500:3500 --env-file .env --name ultimate-lists-app ultimate-lists-app +``` diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e38ef79 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,50 @@ +# Use Node.js LTS version +FROM node:20-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Copy package files +COPY package.json package-lock.json* ./ +RUN npm ci + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Generate Prisma Client +RUN npx prisma generate + +# Build Next.js application +ENV NEXT_TELEMETRY_DISABLED 1 +RUN npm run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV production +ENV NEXT_TELEMETRY_DISABLED 1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy necessary files +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma +COPY --from=builder /app/prisma ./prisma + +USER nextjs + +EXPOSE 3500 + +ENV PORT 3500 +ENV HOSTNAME "0.0.0.0" + +CMD ["node", "server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c42d83d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,43 @@ +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "3500:3500" + environment: + - NODE_ENV=production + - DATABASE_URL=${DATABASE_URL} + - NEXTAUTH_URL=${NEXTAUTH_URL:-http://localhost:3500} + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} + - AUTH_SECRET=${AUTH_SECRET} + restart: unless-stopped + depends_on: + - db-check + networks: + - app-network + + # Health check service to ensure MySQL is accessible + db-check: + image: mysql:8.0 + command: > + sh -c " + until mysqladmin ping -h$${DB_HOST} -P$${DB_PORT} -u$${DB_USER} -p$${DB_PASSWORD} --silent; do + echo 'Waiting for MySQL...'; + sleep 2; + done; + echo 'MySQL is ready!'; + " + environment: + - DB_HOST=${DB_HOST:-localhost} + - DB_PORT=${DB_PORT:-3306} + - DB_USER=${DB_USER:-root} + - DB_PASSWORD=${DB_PASSWORD} + networks: + - app-network + +networks: + app-network: + driver: bridge diff --git a/next.config.js b/next.config.js index 9761814..b90208e 100644 --- a/next.config.js +++ b/next.config.js @@ -1,5 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + output: 'standalone', experimental: { optimizePackageImports: ['lucide-react'], },