diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..ca79ca5b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 00000000..9bc8b42c --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,70 @@ +name: Build and Push Docker Image + +on: + push: + tags: + - 'v*' + # Uncomment to also build on master pushes (rolling latest). + # Pair with concurrency + paths below to avoid excessive builds. + # branches: + # - master + # paths: + # - 'src/**' + # - 'open-sse/**' + # - 'public/**' + # - 'package*.json' + # - 'next.config.*' + # - 'Dockerfile' + workflow_dispatch: + +# Uncomment if re-enabling master push trigger. +# concurrency: +# group: docker-${{ github.ref }} +# cancel-in-progress: true + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + + - uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=sha,prefix= + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max + platforms: linux/amd64 + provenance: false + sbom: false diff --git a/Dockerfile b/Dockerfile index 5d2491cf..b5bcae14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,7 @@ COPY package*.json ./ RUN if [ -f package-lock.json ]; then npm ci --no-audit --no-fund; else npm install --no-audit --no-fund; fi COPY . ./ +ENV NEXT_TELEMETRY_DISABLED=1 RUN npm run build FROM node:20-alpine AS runner @@ -15,15 +16,20 @@ LABEL org.opencontainers.image.title="9router" ENV NODE_ENV=production ENV PORT=20128 ENV HOSTNAME=0.0.0.0 - -# Runtime writable location for localDb when DATA_DIR is configured to /app/data -RUN mkdir -p /app/data +ENV NEXT_TELEMETRY_DISABLED=1 COPY --from=builder /app/public ./public COPY --from=builder /app/.next/static ./.next/static COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/open-sse ./open-sse +RUN mkdir -p /app/data + +# Fix permissions at runtime (handles mounted volumes) +RUN printf '#!/bin/sh\nchown -R node:node /app/data 2>/dev/null; exec su-exec node "$@"\n' > /entrypoint.sh && chmod +x /entrypoint.sh +RUN apk add --no-cache su-exec + EXPOSE 20128 +ENTRYPOINT ["/entrypoint.sh"] CMD ["node", "server.js"]