javascript - Getting error while installing dependency manually on render environment - Stack Overflow

I am unable to deploy my dockerized application on render I am using puppeteer-real-browser library whi

I am unable to deploy my dockerized application on render I am using puppeteer-real-browser library which requires xvfb to be installed if ran on linux OS.

I am using Chromium Version 130.0.6723.58 on my Linux (ubuntu)

It works fine locally as i installed xvfb but during deployment on render its throwing error.

Here's the Dockerfile:

FROM ghcr.io/puppeteer/puppeteer:19.7.2
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
RUN apt-get update && apt-get install -y xvfb
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["xvfb-run", "--server-args=-screen 0 1024x768x24", "node", "index.js"]

Here's the error i see on render's logs:

#6 [2/6] RUN apt-get update && apt-get install -y xvfb
#6 0.050 Reading package lists...
#6 0.061 E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
#6 0.061 W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
#6 0.061 W: Target Packages (main/binary-all/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
#6 ERROR: process "/bin/sh -c apt-get update && apt-get install -y xvfb" did not complete successfully: exit code: 100

 > [2/6] RUN apt-get update && apt-get install -y xvfb:
0.061 E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
0.061 W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
0.061 W: Target Packages (main/binary-all/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1

Dockerfile:9

   7 |     
   8 |     # Install xvfb
   9 | >>> RUN apt-get update && apt-get install -y xvfb
  10 |     
  11 |     # Set working directory
error: failed to solve: process "/bin/sh -c apt-get update && apt-get install -y xvfb" did not complete successfully: exit code: 100
error: exit status 1

Here's my index.js file

const express = require("express");
const puppeteer = require("puppeteer");
const { connect } = require("puppeteer-real-browser");
const cors = require("cors");
require("dotenv").config();
const app = express();
app.use(cors());

const base = process.env.BASE_URL;
const PORT = process.env.PORT;

app.get("/wakeup", (req, res) => res.send("Server is awake!"));

app.get("/search", async (req, res) => {
  const query = req.query.q;
  if (!query) return res.status(400).json({ Error: "Missing query param 'q'" });

  let books = null;
  query.length >= 2 ? (books = await searchBooks(query)) : null;
  if (!books || books.length === 0)
    return res
      .status(404)
      .json({ Error: "Book not found, try different one!" });

  res.json(books);
});

app.get("/ebook", async (req, res) => {
  const { url } = req.query;
  if (!url) return res.status(400).json({ error: "Missing query 'url'" });

  const downloadUrl = await getDownloadLink(url);
  if (!downloadUrl.ebook)
    return res
      .status(404)
      .json({ Error: "Ebook not found, try different one!" });
  res.json(downloadUrl);
});

const searchBooks = async (title) => {
  const browser = await puppeteer.launch({
    headless: true,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });
  const page = await browser.newPage();
  await page.setUserAgent(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
  );

  try {
    await page.goto(`${base}/?s=${title}&page=1`, {
      waitUntil: "networkidle2",
    });
    // await page.type('input[name="q"]', title);
    // await page.keyboard.press('Enter');
    await page.waitForSelector("#genesis-content", { timeout: 20000 });

    const books = await page.evaluate((baseUrl) => {
      return Array.from(
        document.querySelectorAll("#genesis-content .post")
      ).map((book) => ({
        title: book.querySelector(".entry-title a")?.textContent.trim(),
        year: book.querySelector(".entry-meta .entry-time")?.textContent.trim(),
        thumbnail: book
          .querySelector(".entry-image-link img")
          ?.getAttribute("src"),
        url: `${book.querySelector(".entry-image-link")?.getAttribute("href")}`,
      }));
    }, base);

    return books;
  } catch (error) {
    handleErrors(error, "searchBooks");
  } finally {
    await browser.close();
  }
};

const getDownloadLink = async (bookUrl) => {
  const { page, browser } = await connect({
    headless: false,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });

  // const page = await browser.newPage();
  await page.setUserAgent(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
  );

  try {
    await page.goto(bookUrl, { waitUntil: "networkidle2" });
    await new Promise((resolve) => setTimeout(resolve, 5000));

    await page.mouse.move(100, 100);
    await new Promise((resolve) => setTimeout(resolve, 1000)); // Short delay

    const buttonSelector = `form[action="${base}/Fetching_Resource.php"]`;
    await page.waitForSelector(buttonSelector);
    await page.mouse.move(120, 120);
    await page.click(buttonSelector);

    const newTarget = await browser.waitForTarget(
      (target) => target.opener() === page.target(),
      { timeout: 10000 }
    );
    const newPage = await newTarget.page();

    let lastValidLink = null;

    newPage.on("response", async (response) => {
      const url = response.url();
      //   console.log("Response URL:", url);

      if (url.includes("fs4.oceanofpdf") && url.includes(".pdf")) {
        lastValidLink = url;
      }
    });

    const maxWaitTime = 30000;
    const interval = 1000;
    let elapsedTime = 0;

    while (!lastValidLink && elapsedTime < maxWaitTime) {
      await new Promise((resolve) => setTimeout(resolve, interval));
      elapsedTime += interval;
    }

    if (lastValidLink) return { ebook: lastValidLink };
    if (!lastValidLink) return { Error: "Sorry ebook not found!" };
  } catch (error) {
    // console.error("Error in downloadBookOne function:", error);
    return { Error: "Sorry ebook not found!" };
  } finally {
    await browser.close();
  }
};

const handleErrors = (error, functionName) => {
  console.error(`Error in ${functionName}:`, error.message);
};

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});


here's package.json

{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "commonjs",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.21.1",
    "puppeteer": "^19.7.2",
    "puppeteer-real-browser": "^1.3.17"
  }
}

The Base_URL will be

I am unable to deploy my dockerized application on render I am using puppeteer-real-browser library which requires xvfb to be installed if ran on linux OS.

I am using Chromium Version 130.0.6723.58 on my Linux (ubuntu)

It works fine locally as i installed xvfb but during deployment on render its throwing error.

Here's the Dockerfile:

FROM ghcr.io/puppeteer/puppeteer:19.7.2
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
RUN apt-get update && apt-get install -y xvfb
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["xvfb-run", "--server-args=-screen 0 1024x768x24", "node", "index.js"]

Here's the error i see on render's logs:

#6 [2/6] RUN apt-get update && apt-get install -y xvfb
#6 0.050 Reading package lists...
#6 0.061 E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
#6 0.061 W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
#6 0.061 W: Target Packages (main/binary-all/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
#6 ERROR: process "/bin/sh -c apt-get update && apt-get install -y xvfb" did not complete successfully: exit code: 100

 > [2/6] RUN apt-get update && apt-get install -y xvfb:
0.061 E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
0.061 W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
0.061 W: Target Packages (main/binary-all/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1

Dockerfile:9

   7 |     
   8 |     # Install xvfb
   9 | >>> RUN apt-get update && apt-get install -y xvfb
  10 |     
  11 |     # Set working directory
error: failed to solve: process "/bin/sh -c apt-get update && apt-get install -y xvfb" did not complete successfully: exit code: 100
error: exit status 1

Here's my index.js file

const express = require("express");
const puppeteer = require("puppeteer");
const { connect } = require("puppeteer-real-browser");
const cors = require("cors");
require("dotenv").config();
const app = express();
app.use(cors());

const base = process.env.BASE_URL;
const PORT = process.env.PORT;

app.get("/wakeup", (req, res) => res.send("Server is awake!"));

app.get("/search", async (req, res) => {
  const query = req.query.q;
  if (!query) return res.status(400).json({ Error: "Missing query param 'q'" });

  let books = null;
  query.length >= 2 ? (books = await searchBooks(query)) : null;
  if (!books || books.length === 0)
    return res
      .status(404)
      .json({ Error: "Book not found, try different one!" });

  res.json(books);
});

app.get("/ebook", async (req, res) => {
  const { url } = req.query;
  if (!url) return res.status(400).json({ error: "Missing query 'url'" });

  const downloadUrl = await getDownloadLink(url);
  if (!downloadUrl.ebook)
    return res
      .status(404)
      .json({ Error: "Ebook not found, try different one!" });
  res.json(downloadUrl);
});

const searchBooks = async (title) => {
  const browser = await puppeteer.launch({
    headless: true,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });
  const page = await browser.newPage();
  await page.setUserAgent(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
  );

  try {
    await page.goto(`${base}/?s=${title}&page=1`, {
      waitUntil: "networkidle2",
    });
    // await page.type('input[name="q"]', title);
    // await page.keyboard.press('Enter');
    await page.waitForSelector("#genesis-content", { timeout: 20000 });

    const books = await page.evaluate((baseUrl) => {
      return Array.from(
        document.querySelectorAll("#genesis-content .post")
      ).map((book) => ({
        title: book.querySelector(".entry-title a")?.textContent.trim(),
        year: book.querySelector(".entry-meta .entry-time")?.textContent.trim(),
        thumbnail: book
          .querySelector(".entry-image-link img")
          ?.getAttribute("src"),
        url: `${book.querySelector(".entry-image-link")?.getAttribute("href")}`,
      }));
    }, base);

    return books;
  } catch (error) {
    handleErrors(error, "searchBooks");
  } finally {
    await browser.close();
  }
};

const getDownloadLink = async (bookUrl) => {
  const { page, browser } = await connect({
    headless: false,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });

  // const page = await browser.newPage();
  await page.setUserAgent(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
  );

  try {
    await page.goto(bookUrl, { waitUntil: "networkidle2" });
    await new Promise((resolve) => setTimeout(resolve, 5000));

    await page.mouse.move(100, 100);
    await new Promise((resolve) => setTimeout(resolve, 1000)); // Short delay

    const buttonSelector = `form[action="${base}/Fetching_Resource.php"]`;
    await page.waitForSelector(buttonSelector);
    await page.mouse.move(120, 120);
    await page.click(buttonSelector);

    const newTarget = await browser.waitForTarget(
      (target) => target.opener() === page.target(),
      { timeout: 10000 }
    );
    const newPage = await newTarget.page();

    let lastValidLink = null;

    newPage.on("response", async (response) => {
      const url = response.url();
      //   console.log("Response URL:", url);

      if (url.includes("fs4.oceanofpdf") && url.includes(".pdf")) {
        lastValidLink = url;
      }
    });

    const maxWaitTime = 30000;
    const interval = 1000;
    let elapsedTime = 0;

    while (!lastValidLink && elapsedTime < maxWaitTime) {
      await new Promise((resolve) => setTimeout(resolve, interval));
      elapsedTime += interval;
    }

    if (lastValidLink) return { ebook: lastValidLink };
    if (!lastValidLink) return { Error: "Sorry ebook not found!" };
  } catch (error) {
    // console.error("Error in downloadBookOne function:", error);
    return { Error: "Sorry ebook not found!" };
  } finally {
    await browser.close();
  }
};

const handleErrors = (error, functionName) => {
  console.error(`Error in ${functionName}:`, error.message);
};

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});


here's package.json

{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "commonjs",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.21.1",
    "puppeteer": "^19.7.2",
    "puppeteer-real-browser": "^1.3.17"
  }
}

The Base_URL will be https://oceanofpdf

Share Improve this question edited Nov 16, 2024 at 17:25 ggorlen 58.1k8 gold badges115 silver badges157 bronze badges asked Nov 16, 2024 at 8:30 KuldeepKuldeep 12 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0
#6 [2/6] RUN apt-get update && apt-get install -y xvfb
#6 0.050 Reading package lists...
#6 0.061 E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
#6 0.061 W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
#6 0.061 W: Target Packages (main/binary-all/Packages) is configured multiple times in /etc/apt/sources.list.d/google-chrome.list:3 and /etc/apt/sources.list.d/google.list:1
#6 ERROR: process "/bin/sh -c apt-get update && apt-get install -y xvfb" did not complete successfully: exit code: 100

apt commands must be run as root, and your base image changes the user. You can change the user in the Dockerfile with:

USER root

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745662840a4638941.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信