ci: add optimized Docker publish workflow from PR #281

- Add Docker build and publish workflow (trigger on v* tag push and manual dispatch only)
- Add Dependabot weekly updates for GitHub Actions versions
- Harden Dockerfile: non-root user, entrypoint permission fix, NEXT_TELEMETRY_DISABLED

Made-with: Cursor
This commit is contained in:
Doan Minh Tu
2026-03-14 16:53:31 +07:00
committed by decolua
3 changed files with 85 additions and 3 deletions

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly

70
.github/workflows/docker-publish.yml vendored Normal file
View File

@@ -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

View File

@@ -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"]