diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5ab570c --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +{ + "name": "git-to.dev", + "build": { + "dockerfile": "../Dockerfile", + "context": "..", + "target": "development" + }, + "workspaceFolder": "/workspace/${localWorkspaceFolderBasename}", + "remoteUser": "node", + "forwardPorts": [3000], + "portsAttributes": { + "3000": { + "label": "Next.js development server", + "onAutoForward": "notify" + } + }, + "postCreateCommand": "pnpm install --frozen-lockfile", + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "bradlc.vscode-tailwindcss" + ] + } + } +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b0a6e85 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.git +.github +.next +.devcontainer +node_modules +.env* +!.env.example +npm-debug.log* +pnpm-debug.log* +README.md diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml new file mode 100644 index 0000000..6235864 --- /dev/null +++ b/.github/workflows/devcontainer.yml @@ -0,0 +1,22 @@ +name: Dev Container + +on: + pull_request: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Build dev container + uses: devcontainers/ci@v0.3 + with: + configFile: .devcontainer/devcontainer.json + push: never diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..7f901e5 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,26 @@ +name: Docker + +on: + pull_request: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: false diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..72e0cd4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +# syntax=docker/dockerfile:1 + +ARG NODE_VERSION=22 +ARG PNPM_VERSION=10.14.0 + +FROM node:${NODE_VERSION}-bookworm-slim AS base +ARG PNPM_VERSION +ENV NEXT_TELEMETRY_DISABLED=1 \ + PNPM_HOME=/pnpm \ + PATH=/pnpm:${PATH} +RUN npm install --global "pnpm@${PNPM_VERSION}" +WORKDIR /app + +FROM base AS dependencies +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +FROM dependencies AS development +ENV NODE_ENV=development +RUN chown -R node:node /app +USER node +EXPOSE 3000 +CMD ["pnpm", "dev", "--hostname", "0.0.0.0"] + +FROM dependencies AS builder +COPY . . +RUN pnpm build + +FROM node:${NODE_VERSION}-bookworm-slim AS runner +ENV NODE_ENV=production \ + NEXT_TELEMETRY_DISABLED=1 \ + HOSTNAME=0.0.0.0 \ + PORT=3000 +WORKDIR /app + +RUN addgroup --system --gid 1001 nodejs \ + && adduser --system --uid 1001 nextjs + +COPY --from=builder --chown=nextjs:nodejs /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/README.md b/README.md index 54b6023..2c90941 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,34 @@ Open [http://localhost:3000](http://localhost:3000). Set `GITHUB_TOKEN` (or `GH_TOKEN`) to increase GitHub API rate limits; unauthenticated requests are supported. -## Checks +## Docker + +Build and run the production image: + +```bash +docker build -t git-to-dev . +docker run --rm -p 3000:3000 git-to-dev +``` + +The image uses Next.js standalone output and runs as an unprivileged user. To use +authenticated GitHub API requests, pass a token when starting the container: + +```bash +docker run --rm -p 3000:3000 -e GITHUB_TOKEN git-to-dev +``` + +## Development container + +Open the repository in a [Development Containers](https://containers.dev/) +compatible editor and choose **Reopen in Container**. The development container +builds the `development` target from the same `Dockerfile`, installs the locked +dependencies, and forwards port 3000. Start the app from its terminal with: + +```bash +pnpm dev +``` + +## Learn More ```bash pnpm lint diff --git a/next.config.mjs b/next.config.mjs index 4cd9948..0013134 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,5 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + output: "standalone", typescript: { ignoreBuildErrors: true, },