diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8dca062 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,21 @@ +# dependencies +node_modules +pnpm-lock.yaml +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# next +.next +out + +# misc +.DS_Store +.git +.gitignore +.cache + +# editor +.vscode +.idea + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..40b9906 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,120 @@ +# syntax=docker/dockerfile:1 + +FROM node:20-alpine AS deps +WORKDIR /app + +# Install system dependencies needed for native modules (especially node-pty) +RUN apk add --no-cache \ + libc6-compat \ + python3 \ + make \ + g++ \ + git \ + bash \ + curl \ + ca-certificates \ + openssl \ + pkgconfig \ + # Additional dependencies for native modules + linux-headers \ + # Dependencies for node-pty and other native packages + libstdc++ \ + # For better compatibility + musl-dev + +# Install bun globally with proper setup +RUN npm install -g bun +# Ensure bun is properly linked and available +RUN ln -sf /usr/local/bin/bun /usr/bin/bun + +# Copy package files +COPY package.json package-lock.json* pnpm-lock.yaml* yarn.lock* ./ + +# Install dependencies with proper fallback +RUN if [ -f pnpm-lock.yaml ]; then \ + corepack enable && corepack prepare pnpm@9.12.3 --activate && pnpm install --frozen-lockfile; \ + elif [ -f package-lock.json ]; then \ + npm ci --build-from-source; \ + elif [ -f yarn.lock ]; then \ + corepack enable && corepack prepare yarn@1.22.22 --activate && yarn install --frozen-lockfile; \ + else \ + npm install --build-from-source; \ + fi + +FROM node:20-alpine AS builder +WORKDIR /app + +# Install build dependencies for native modules +RUN apk add --no-cache \ + python3 \ + make \ + g++ \ + git \ + linux-headers \ + musl-dev \ + pkgconfig + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Set environment variables for build +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +# Build the application +RUN npm run build + +FROM node:20-alpine AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +# Install runtime dependencies needed for native modules +RUN apk add --no-cache \ + libc6-compat \ + # Runtime dependencies for node-pty + libstdc++ \ + # For database connections + ca-certificates \ + # For better compatibility + musl + +# Create non-root user +RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 + +# Copy package.json and configuration files +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/public ./public +COPY --from=builder /app/tsconfig.json ./tsconfig.json +COPY --from=builder /app/bunfig.toml ./bunfig.toml + +# Copy environment file for database connections +COPY .env .env + +# Copy Next.js build output +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +# Copy source files needed for database operations +COPY --from=builder /app/src ./src + +# Copy bun from deps stage with proper setup +COPY --from=deps /usr/local/bin/bun /usr/local/bin/bun +COPY --from=deps /usr/local/lib/node_modules/bun /usr/local/lib/node_modules/bun +# Ensure bun is accessible +RUN ln -sf /usr/local/bin/bun /usr/bin/bun + +# Copy node_modules for runtime dependencies +COPY --from=deps /app/node_modules ./node_modules + +# Set proper permissions +RUN chown -R nextjs:nodejs /app + +ENV PORT=${PORT:-3000} +EXPOSE ${PORT:-3000} + +USER nextjs + +# Start the standalone server +CMD ["node", "server.js"] diff --git a/README.md b/README.md index 19a7240..4377382 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,28 @@ App will be running on [http://localhost:3000](http://localhost:3000). --- +#### Docker support + +**Build and Run** + ```bash + # Build the Docker image + docker build -t ciscode-app:latest . + + # Or use docker-compose (recommended) + docker compose up -d --build + ``` +**Database Connection** + + If you are locally hosting your database, it is recommended that you also use a container for mysql. + in the docker-compose.yml... + + ``` + network_mode: "host" + ``` + + ...denotes that the database must be locally hosted. it would still also use the db credentials that you input in the .env + + ## 🤝 Contributing Contributions are welcome! Feel free to fork the repo, submit issues, or open pull requests. diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..1e1938c --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[alias] +"@/" = "./src/" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b59bb2a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,21 @@ +services: + app: + build: . + image: ciscode-app:latest + environment: + - NODE_ENV=production + - PORT=${PORT} + - DB_HOST=${DB_HOST} + - DB_PORT=${DB_PORT} + - DB_USER=${DB_USER} + - DB_PASSWORD=${DB_PASSWORD} + - DB_NAME=${DB_NAME} + - JWT_SECRET=${JWT_SECRET} + ports: + - "${PORT}:${PORT}" + restart: unless-stopped + env_file: + - .env + # Using bridge network instead of host network for better port accessibility + extra_hosts: + - "host.docker.internal:host-gateway" \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index e9ffa30..ed2939f 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,9 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + output: 'standalone', + assetPrefix: process.env.NODE_ENV === 'production' ? '' : undefined, + trailingSlash: false, }; export default nextConfig; diff --git a/package.json b/package.json index a1abee5..7dafb28 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "build": "next build", "start": "dotenv -- next start", "lint": "next lint", - "db:sync": "bun run src/db/sync.ts", - "db:seed": "bun run src/db/seed.ts", - "db:reset": "bun run src/db/sync.ts && bun run src/db/seed.ts", + "db:sync": "bun build src/db/sync.ts --target=node --outfile=/tmp/sync.mjs && node /tmp/sync.mjs", + "db:seed": "bun build src/db/seed.ts --target=node --outfile=/tmp/seed.mjs && node /tmp/seed.mjs", + "db:reset": "bun build src/db/sync.ts --target=node --outfile=/tmp/sync.mjs && node /tmp/sync.mjs && bun build src/db/seed.ts --target=node --outfile=/tmp/seed.mjs && node /tmp/seed.mjs", "prepare": "husky install" }, "dependencies": {