From ff1330868e3259cfee1fa43ca47d0b9657dcfadd Mon Sep 17 00:00:00 2001 From: root Date: Thu, 11 Sep 2025 07:31:02 +0000 Subject: [PATCH 1/7] Add Github Workflow --- .github/workflows/docker-build-push.yaml | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/docker-build-push.yaml diff --git a/.github/workflows/docker-build-push.yaml b/.github/workflows/docker-build-push.yaml new file mode 100644 index 0000000..2e5b200 --- /dev/null +++ b/.github/workflows/docker-build-push.yaml @@ -0,0 +1,27 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout the repository + uses: actions/checkout@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + push: true + tags: ${{ secrets.DOCKER_USERNAME }}/playwright-domain-scanner:latest + From fb133dff6c5b226e20e6e139678e85b1714ac9f8 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 11 Sep 2025 07:31:31 +0000 Subject: [PATCH 2/7] Add Github Workflow --- .forgejo/workflows/docker-build-push.yaml | 42 ----------------------- 1 file changed, 42 deletions(-) delete mode 100644 .forgejo/workflows/docker-build-push.yaml diff --git a/.forgejo/workflows/docker-build-push.yaml b/.forgejo/workflows/docker-build-push.yaml deleted file mode 100644 index 340cceb..0000000 --- a/.forgejo/workflows/docker-build-push.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: Build and Push Docker Image - -on: - push: - branches: - - main - paths: - - '**/*' # Триггер при любом изменении репозитория - -jobs: - build-and-push: - runs-on: docker - - container: - image: docker:24.0.1 - - steps: - # Установка Docker CLI (если не в базовом образе) - - name: Setup Docker CLI - run: | - apk add --no-cache docker-cli - - # Авторизация в Docker Hub - токен необходимо добавить в Secrets - - name: Login to Docker Hub - env: - DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - run: | - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - - # Клонирование исходников — встроено в Forgejo Actions - - # Сборка Docker образа - - name: Build Docker Image - run: | - docker build -t ${DOCKER_USERNAME}/playwright-domain-scanner:latest . - - # Push образ на Docker Hub - - name: Push Docker Image - run: | - docker push ${DOCKER_USERNAME}/playwright-domain-scanner:latest - From e1911bf5e8c075ccce305e3dd8c546d09908dd51 Mon Sep 17 00:00:00 2001 From: g00dvin Date: Thu, 11 Sep 2025 07:45:35 +0000 Subject: [PATCH 3/7] Fix dockerhub image name --- .github/workflows/docker-build-push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build-push.yaml b/.github/workflows/docker-build-push.yaml index 2e5b200..3933b65 100644 --- a/.github/workflows/docker-build-push.yaml +++ b/.github/workflows/docker-build-push.yaml @@ -23,5 +23,5 @@ jobs: uses: docker/build-push-action@v4 with: push: true - tags: ${{ secrets.DOCKER_USERNAME }}/playwright-domain-scanner:latest + tags: ${{ secrets.DOCKER_USERNAME }}/gekata:latest From 7c2a58c894d47bb700b047473a8effb2c218b919 Mon Sep 17 00:00:00 2001 From: g00dvin Date: Thu, 11 Sep 2025 07:57:09 +0000 Subject: [PATCH 4/7] Add env setting to workflow --- .github/workflows/docker-build-push.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker-build-push.yaml b/.github/workflows/docker-build-push.yaml index 3933b65..be6ac82 100644 --- a/.github/workflows/docker-build-push.yaml +++ b/.github/workflows/docker-build-push.yaml @@ -8,6 +8,7 @@ on: jobs: build-and-push: runs-on: ubuntu-latest + environment: dockerhub steps: - name: Checkout the repository From 46b32d6aa7c656cefc55cfbc3a3603bc4a9b8167 Mon Sep 17 00:00:00 2001 From: g00dvin Date: Thu, 11 Sep 2025 08:08:43 +0000 Subject: [PATCH 5/7] Change base image for OCI --- Dockerfile | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/Dockerfile b/Dockerfile index f95e58b..94123d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,46 +1,18 @@ -# Use official Node.js LTS base image -FROM node:20-slim +FROM mcr.microsoft.com/playwright:v1.42.0-jammy -# Install dependencies for running Chromium -RUN apt-get update && apt-get install -y \ - ca-certificates \ - fonts-liberation \ - libasound2 \ - libatk-bridge2.0-0 \ - libatk1.0-0 \ - libcups2 \ - libdbus-1-3 \ - libdrm2 \ - libgbm1 \ - libgtk-3-0 \ - libnspr4 \ - libnss3 \ - libx11-xcb1 \ - libxcomposite1 \ - libxdamage1 \ - libxrandr2 \ - xdg-utils \ - wget \ - --no-install-recommends && \ - rm -rf /var/lib/apt/lists/* - -# Set working directory WORKDIR /usr/src/app -# Copy package files and install dependencies COPY package*.json ./ COPY ignore-domains.txt ./ -RUN npm ci -# Install Playwright browsers (Chromium) +RUN npm ci --omit=dev RUN npx playwright install chromium -# Copy app sources COPY . . -# Expose port +RUN rm -rf /usr/local/share/doc /usr/local/share/man /usr/local/share/info + EXPOSE 3000 -# Run the service CMD ["npm", "start"] From cdd36afd3353769d49415d4d2ba970db6fc07b9c Mon Sep 17 00:00:00 2001 From: g00dvin Date: Thu, 11 Sep 2025 09:23:02 +0000 Subject: [PATCH 6/7] Change base image for OSI to trixie:slim --- Dockerfile | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 94123d5..29b2c59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,25 @@ -FROM mcr.microsoft.com/playwright:v1.42.0-jammy +FROM node:20-trixie-slim +ENV DEBIAN_FRONTEND=noninteractive WORKDIR /usr/src/app +# Базовые утилиты, без лишних рекоммендованных пакетов +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates curl gnupg && \ + rm -rf /var/lib/apt/lists/* + COPY package*.json ./ +RUN npm ci --omit=dev + +# Ставим только headless shell Chromium и его системные зависимости +RUN npx playwright install --with-deps --only-shell && \ + rm -rf /usr/share/doc /usr/share/man /var/cache/apt/* + +# Копируем минимально нужные исходники +COPY server.js ./ +# Если используется игнор-лист как файл — раскомментируйте строку: COPY ignore-domains.txt ./ -RUN npm ci --omit=dev -RUN npx playwright install chromium - -COPY . . - -RUN rm -rf /usr/local/share/doc /usr/local/share/man /usr/local/share/info - EXPOSE 3000 - -CMD ["npm", "start"] +CMD ["node", "server.js"] From 09f054b8884ae41d0d08ed4a1052d9107d522063 Mon Sep 17 00:00:00 2001 From: g00dvin Date: Thu, 11 Sep 2025 09:59:28 +0000 Subject: [PATCH 7/7] Use headless chromium --- Dockerfile | 47 +++++++++++++++++++++++++++++++++++------------ server.js | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index 29b2c59..adf380a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,48 @@ -FROM node:20-trixie-slim +# Base minimal Debian +FROM debian:bookworm-slim +# Prevent tzdata prompts ENV DEBIAN_FRONTEND=noninteractive -WORKDIR /usr/src/app -# Базовые утилиты, без лишних рекоммендованных пакетов +# Install Node.js, Chromium and minimal runtime libs +# Note: chromium package on Debian provides /usr/bin/chromium RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates curl gnupg && \ - rm -rf /var/lib/apt/lists/* + ca-certificates curl gnupg \ + nodejs npm \ + chromium \ + # Minimal GUI/Chromium runtime libs often needed by Playwright Chromium + libx11-6 libxcomposite1 libxdamage1 libxrandr2 libxkbcommon0 \ + libgtk-3-0 libnss3 libdrm2 libgbm1 libasound2 fonts-liberation \ + # Useful for font rendering + fonts-dejavu-core \ + && rm -rf /var/lib/apt/lists/* +# App directory +WORKDIR /app + +# Install only production deps COPY package*.json ./ +ENV CI=true RUN npm ci --omit=dev -# Ставим только headless shell Chromium и его системные зависимости -RUN npx playwright install --with-deps --only-shell && \ - rm -rf /usr/share/doc /usr/share/man /var/cache/apt/* +# Copy source +COPY . . -# Копируем минимально нужные исходники -COPY server.js ./ -# Если используется игнор-лист как файл — раскомментируйте строку: -COPY ignore-domains.txt ./ +# Security: run as non-root +RUN useradd -ms /bin/bash nodeuser && chown -R nodeuser:nodeuser /app +USER nodeuser +# Environment for service +ENV PORT=3000 \ + # Ensure Playwright uses system Chromium and does not download browsers + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \ + PLAYWRIGHT_BROWSERS_PATH=0 \ + # Explicit executable if needed in code; here server uses default, so optional + CHROMIUM_PATH=/usr/bin/chromium + +# Expose service port EXPOSE 3000 + +# Start the service CMD ["node", "server.js"] diff --git a/server.js b/server.js index f6ef7fe..dde4a67 100644 --- a/server.js +++ b/server.js @@ -1,9 +1,22 @@ +// server.js const express = require('express'); const { chromium } = require('playwright'); const app = express(); const port = process.env.PORT || 3000; +// Использовать системный Chromium, если задан путь (например, /usr/bin/chromium в Debian) +const executablePath = process.env.CHROMIUM_PATH || undefined; // можно оставить undefined, если Chromium в PATH [1][2] + +// Базовый набор флагов для контейнера без systemd/dbus и без install-deps +const chromiumArgs = [ + '--no-sandbox', // запуск без setuid sandbox в контейнере [14] + '--disable-setuid-sandbox', // отключение setuid sandbox [14] + '--disable-dev-shm-usage', // использовать /tmp вместо /dev/shm (если нет --ipc=host) [15][16] + '--disable-gpu', // headless окружение [14] + '--no-zygote', // упрощение процессов в контейнере [14] +]; + app.use(express.json()); function extractDomain(url) { @@ -23,12 +36,17 @@ app.get('/domains', async (req, res) => { const url = `https://${domain}`; const seenDomains = new Set(); + let browser; + let context; try { - const browser = await chromium.launch({ - args: ['--no-sandbox', '--disable-setuid-sandbox'] + browser = await chromium.launch({ + executablePath, // берётся из CHROMIUM_PATH при наличии [1][2] + headless: true, // явный headless режим для контейнера [14] + args: chromiumArgs, // флаги для стабильности в Docker [15][14] }); - const context = await browser.newContext(); + + context = await browser.newContext(); const page = await context.newPage(); page.on('request', request => { @@ -37,15 +55,20 @@ app.get('/domains', async (req, res) => { }); await page.goto(url, { waitUntil: 'load', timeout: 30000 }); + + // Фильтрация доменов после закрытия страницы + await context.close(); await browser.close(); - // Фильтрация доменов - const filteredDomains = Array.from(seenDomains).filter(d => - !d.includes('doubleclick') && !d.includes('google') - ).sort(); + const filteredDomains = Array.from(seenDomains) + .filter(d => !d.includes('doubleclick') && !d.includes('google')) + .sort(); res.json({ domains: filteredDomains }); } catch (e) { + // Безопасно закрыть ресурсы при ошибке + try { if (context) await context.close(); } catch {} + try { if (browser) await browser.close(); } catch {} res.status(500).json({ error: e.message || 'Internal server error' }); } });