diff --git a/.gitea/workflows/docker-build-push.yml b/.gitea/workflows/docker-build-push.yml new file mode 100644 index 00000000..7266b452 --- /dev/null +++ b/.gitea/workflows/docker-build-push.yml @@ -0,0 +1,67 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - "master" + - "release/*" + tags: + - "*" + workflow_dispatch: + +jobs: + docker: + runs-on: ubuntu-latest + if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + # Ensure full history and all tags are available + fetch-depth: 0 + + - name: Set up QEMU (multi-arch) + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: gitea.suda.codes/${{ github.repository }} + tags: | + type=ref,event=tag + + - name: Determine latest Git tag + id: latest + shell: bash + run: | + set -euo pipefail + # Fetch tags in case the runner's mirror is stale + git fetch --tags --force --quiet || true + if tag=$(git describe --tags --abbrev=0 2>/dev/null); then + echo "tag=$tag" >> "$GITHUB_OUTPUT" + else + # Fallback when no tags exist + echo "tag=latest" >> "$GITHUB_OUTPUT" + fi + + - name: Log in to container registry + uses: docker/login-action@v3 + with: + registry: gitea.suda.codes + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + # Always tag with the latest Git tag; also keep any tags from metadata (e.g., on tag events) + tags: | + ${{ steps.meta.outputs.tags }} + gitea.suda.codes/${{ github.repository }}:${{ steps.latest.outputs.tag }} + diff --git a/Dockerfile b/Dockerfile index 3ff5209a..3b93735a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,37 +1,59 @@ -# Base image FROM node:20-bookworm-slim -# Copy repository -COPY . /metrics WORKDIR /metrics -# Setup -RUN chmod +x /metrics/source/app/action/index.mjs \ - # Install latest chrome dev package, fonts to support major charsets and skip chromium download on puppeteer install - # Based on https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#running-puppeteer-in-docker - && apt-get update \ - && apt-get install -y wget gnupg ca-certificates libgconf-2-4 \ - && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ - && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ - && apt-get update \ - && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 libx11-xcb1 libxtst6 lsb-release --no-install-recommends \ - # Install deno for miscellaneous scripts - && apt-get install -y curl unzip \ - && curl -fsSL https://deno.land/x/install/install.sh | DENO_INSTALL=/usr/local sh \ - # Install ruby to support github licensed gem - && apt-get install -y ruby-full git g++ cmake pkg-config libssl-dev \ - && gem install licensed \ - # Install python for node-gyp - && apt-get install -y python3 \ - # Clean apt/lists - && rm -rf /var/lib/apt/lists/* \ - # Install node modules and rebuild indexes - && npm ci \ - && npm run build +# Install Google Chrome stable and runtime deps + fonts +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + wget gnupg ca-certificates curl unzip \ + # Chrome runtime deps + libnss3 libxss1 libx11-xcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 \ + libxkbcommon0 libxrandr2 libatk1.0-0 libatk-bridge2.0-0 libgtk-3-0 \ + libgbm1 libasound2 fonts-liberation \ + # Optional fonts for broader charset support + fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf; \ + wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/google-linux.gpg; \ + echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-linux.gpg] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list; \ + apt-get update; \ + apt-get install -y --no-install-recommends google-chrome-stable; \ + rm -rf /var/lib/apt/lists/* -# Environment variables -ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true -ENV PUPPETEER_BROWSER_PATH "google-chrome-stable" +# Prevent Puppeteer from downloading Chromium, point to system Chrome +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable -# Execute GitHub action -ENTRYPOINT node /metrics/source/app/action/index.mjs +# Default Chrome args suitable for containers (headless + no sandbox) +ENV CHROME_DEFAULT_ARGS="--no-sandbox --disable-setuid-sandbox --headless=new --disable-gpu --disable-dev-shm-usage --no-zygote --no-first-run --ozone-platform=none --disable-features=UseOzonePlatform --enable-features=NetworkService,NetworkServiceInProcess" + +# Env consumed by lowlighter/metrics to pass browser flags +ENV METRICS_BROWSER=chromium +ENV METRICS_BROWSER_HEADLESS=true +ENV METRICS_BROWSER_ARGS="" + +# Optional: trust reverse proxy for express-rate-limit +ENV METRICS_TRUST_PROXY=1 + +# Copy sources and install JS deps +COPY package.json package-lock.json* ./ +RUN npm ci + +COPY . . + +# Build the project +RUN npm run build + +# Wrapper entrypoint to ensure args are always set +RUN printf '%s\n' \ +'#!/usr/bin/env bash' \ +'set -euo pipefail' \ +'export PUPPETEER_EXECUTABLE_PATH="${PUPPETEER_EXECUTABLE_PATH:-/usr/bin/google-chrome-stable}"' \ +'export METRICS_BROWSER="${METRICS_BROWSER:-chromium}"' \ +'export METRICS_BROWSER_HEADLESS="${METRICS_BROWSER_HEADLESS:-true}"' \ +'if [ -z "${METRICS_BROWSER_ARGS:-}" ]; then' \ +' export METRICS_BROWSER_ARGS="${CHROME_DEFAULT_ARGS}"' \ +'fi' \ +'exec npm start' \ +> /usr/local/bin/metrics-entrypoint && chmod +x /usr/local/bin/metrics-entrypoint + +ENTRYPOINT ["/usr/local/bin/metrics-entrypoint"]