Anonymous
Получение ошибки при установке зависимости вручную в среде рендеринга
Сообщение
Anonymous » 16 ноя 2024, 11:30
Я не могу развернуть свое докеризованное приложение на render.com. Я использую библиотеку puppeteer-real-browser, которая требует установки xvfb, если она работает в ОС Linux.
Я использую Версия Chromium 130.0.6723.58 на моем Linux (ubuntu)
Он отлично работает локально, поскольку я установил xvfb, но во время развертывания при рендеринге выдает ошибку.
Вот 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"]
Вот ошибка, которую я вижу в журналах рендеринга:
Код: Выделить всё
#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
Вот мой файл index.js
Код: Выделить всё
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.com") && 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}`);
});
вот 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"
}
}
Base_URL будет
https://oceanofpdf.com
Подробнее здесь:
https://stackoverflow.com/questions/791 ... nvironment
1731745837
Anonymous
Я не могу развернуть свое докеризованное приложение на render.com. Я использую библиотеку puppeteer-real-browser, которая требует установки xvfb, если она работает в ОС Linux. Я использую Версия Chromium 130.0.6723.58 на моем Linux (ubuntu) Он отлично работает локально, поскольку я установил xvfb, но во время развертывания при рендеринге выдает ошибку. Вот Dockerfile: [code]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"] [/code] Вот ошибка, которую я вижу в журналах рендеринга: [code]#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 [/code] Вот мой файл index.js [code]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.com") && 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}`); }); [/code] вот package.json [code]{ "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" } } [/code] Base_URL будет https://oceanofpdf.com Подробнее здесь: [url]https://stackoverflow.com/questions/79194762/getting-error-while-installing-dependency-manually-on-render-environment[/url]