i’m trying to run docker on heroku
so i tried
"git add heroku.yml"
"git commit m "Add yml"
"git heroku push"
but as you can see here, heroku log shows me this logs
2022-01-24T04:10:12.979291+00:00 heroku[web.1]: Restarting
2022-01-24T04:10:15.729676+00:00 app[api]: Remove PATH config vars by user [email protected]
2022-01-24T04:10:15.729676+00:00 app[api]: Release v37 created by user [email protected]
2022-01-24T04:10:15.965096+00:00 heroku[web.1]: Restarting
2022-01-24T04:10:21.029250+00:00 heroku[web.1]: Starting process with command `/bin/sh -c bundle exec puma -C config/puma.rb`
2022-01-24T04:10:22.051845+00:00 app[web.1]: /bin/sh: 1: bundle: not found
2022-01-24T04:10:22.172593+00:00 heroku[web.1]: Process exited with status 127
2022-01-24T04:10:39.006056+00:00 heroku[web.1]: Starting process with command `/bin/sh -c bundle exec puma -C config/puma.rb`
2022-01-24T04:10:40.617158+00:00 app[web.1]: /bin/sh: 1: bundle: not found
2022-01-24T04:10:40.794603+00:00 heroku[web.1]: Process exited with status 127
2022-01-24T04:10:40.946303+00:00 heroku[web.1]: State changed from starting to crashed
2022-01-24T04:10:41.842541+00:00 heroku[web.1]: Starting process with command `/bin/sh -c bundle exec puma -C config/puma.rb`
2022-01-24T04:10:43.098998+00:00 app[web.1]: /bin/sh: 1: bundle: not found
2022-01-24T04:10:43.326072+00:00 heroku[web.1]: Process exited with status 127
2022-01-24T04:11:41.000000+00:00 app[api]: Build started by user [email protected]
2022-01-24T04:14:11.000000+00:00 app[api]: Build succeeded
2022-01-24T04:14:11.299638+00:00 app[api]: Release v38 created by user [email protected]
2022-01-24T04:14:12.170626+00:00 heroku[web.1]: State changed from crashed to starting
2022-01-24T04:14:31.949298+00:00 heroku[web.1]: Starting process with command `/bin/sh -c /bin/sh -c bundle\ exec\ puma\ -C\ config/puma.rb`
2022-01-24T04:14:32.978306+00:00 app[web.1]: /bin/sh: 1: bundle: not found
2022-01-24T04:14:33.120489+00:00 heroku[web.1]: Process exited with status 127
2022-01-24T04:14:33.222836+00:00 heroku[web.1]: State changed from starting to crashed
i don’t know what is wrong with it cause this docker file is working on local
but when i run it in heroku, alway shows me this log
so it completely freak me out
my Dockerfile
FROM node:14.17.5
RUN apt-get update &&
apt-get install -yq gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1
libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6
ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
xvfb x11vnc x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps
WORKDIR /app
COPY package.json /app
RUN npm install
COPY . /app
EXPOSE 3001
CMD xvfb-run --server-args="-screen 0 1024x768x24" npm start
# FROM node:14.17.5
# RUN apt-get update &&
# apt-get install -yq gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3
# libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4
# libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1
# libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6
# ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
# xvfb x11vnc x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps
# WORKDIR /app
# COPY package.json /app
# RUN npm install
# COPY . /app
# EXPOSE 8081
# CMD xvfb-run --server-args="-screen 0 1024x768x24" npm start
my server file<index.js> with express.js
import express from "express";
import puppeteer from "puppeteer";
import cors from "cors";
import dotenv from "dotenv";
dotenv.config();
const app = express();
const whitelist = [
"http://localhost:3000",
"my netlify address",
];
const corsOptions = {
origin: (origin, callback) => {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error("Not Allowed Origin!"));
}
},
methods: ["GET", "POST", "PUT", "DELETE"],
credentials: true,
};
app.use(cors());
app.use(express.json());
// 아 맞아 전체 url갖고있으면 굳이 서버 없어도 되잖아
// 그리고 자기 아이디 작성하게 하기
const setIdPw = async (page) => {
// FIXME: 아이디 비밀번호 입력
await page.waitForSelector("input[name=userid]");
await page.waitForSelector("input[name=password]");
await page.$eval("input[name=userid]", (el) => (el.value = "userid"));
await page.$eval("input[name=password]", (el) => (el.value = "userpassword"));
await page.click('input[type="submit"]');
};
const getText = async (page) => {
// FIXME: 텍스트 크롤링
await page.waitForSelector(".article p.large");
const text = await page.evaluate(() => {
const anchor = document.querySelector(".article p.large");
return anchor.innerHTML;
});
return text;
};
const getImg = async (page) => {
try {
await page.waitForSelector(".article .attach img", { timeout: 2000 });
try {
const img = await page.evaluate(() => {
const imgsrc = document
.querySelector(".article .attach img")
.getAttribute("src");
return imgsrc;
});
return img;
} catch (error) {}
} catch (error) {
return "꽝";
}
};
const getProfile = async (page) => {
await page.waitForSelector(".picture.large");
await page.waitForSelector(".profile .large");
const profile = await page.evaluate(() => {
const Pimg = document.querySelector(".picture.large").getAttribute("src");
const username = document.querySelectorAll(".profile .large")[0].innerText;
const date = document.querySelectorAll(".profile .large")[1].innerText;
const url = window.location.href;
return { Pimg, username, date, url };
});
return profile;
};
// FIXME: 검색
app.post("/gotoEta", (req, res) => {
const { url } = req.body;
(async () => {
const options = {
args: [
"--fast-start",
"--disable-web-security",
"--disable-features=IsolateOrigins",
"--disable-site-isolation-trials",
"--disable-extensions",
"--disable-setuid-sandbox",
"--no-sandbox",
],
ignoreHTTPSErrors: true,
headless: false,
ignoreDefaultArgs: ["--disable-extensions"],
};
try {
// FIXME: 초기설정
const browser = await puppeteer.launch(options);
const page = await browser.newPage();
await page.setViewport({ width: 640, height: 768 });
const everytimeUrl = url;
await page.goto(everytimeUrl, [
"load",
"domcontentloaded",
"networkidle0",
]);
setIdPw(page);
// FIXME: 텍스트 / 사진 크롤링
const text = await getText(page);
const img = await getImg(page);
const profile = await getProfile(page);
console.log(profile);
res.json({ text, img, profile });
// FIXME: 브라우져 닫기
await browser.close();
} catch (error) {
console.log("Error " + error.toString());
res.send("오류발생1");
}
})();
});
const gotoNextPage = async (page) => {
try {
await page.waitForSelector("a.next");
await page.click("a.next");
return true;
} catch (err) {
return false;
}
};
const get20Urls = async (page) => {
await page.waitForSelector("#container .wrap.articles article a");
const urlList = await page.evaluate(() => {
const hrefs = document.querySelectorAll(
"#container .wrap.articles article a"
);
let list = [];
hrefs.forEach((val) => {
const href = val.getAttribute("href");
const url = `https://everytime.kr${href}`;
list.push(url);
});
return list;
});
// console.log(urlList);
return urlList;
};
app.get("/getEveryUrls", (req, res) => {
(async () => {
try {
const browser = await puppeteer.launch({
headless: false,
});
const page = await browser.newPage();
await page.setViewport({ width: 640, height: 500 });
const everytimeUrl = `https://everytime.kr/409275/p/1`;
await page.goto(everytimeUrl, [
"load",
"domcontentloaded",
"networkidle0",
]);
setIdPw(page);
let totalUrls = [];
let stopWhile = true;
let i = 0;
while (true) {
try {
const urls = await get20Urls(page);
totalUrls.push(...urls);
stopWhile = await gotoNextPage(page);
i += 1;
console.log(i);
} catch (error) {
break;
}
}
res.json(totalUrls);
console.log(totalUrls);
} catch (err) {
console.log("Error " + error.toString());
console.log("오류발생");
res.send("오류발생");
}
})();
});
app.get("/hi", (req, res) => {
console.log("hi there");
res.send("안녕 반가워");
});
// FIXME: 헤드레스로 만들기
const setIdPwV2 = async (page) => {
// FIXME: 아이디 비밀번호 입력
page.waitForNavigation({ waitUntil: "load" });
// await page.focus("input[name=userid]");
// await page.keyboard.type("hanjk123");
await page.$eval("input[name=userid]", (el) => (el.value = "hanjk123"));
await page.$eval("input[name=password]", (el) => (el.value = "agdsffaith00"));
page.click('input[type="submit"]');
};
const getTextV2 = async (page) => {
// FIXME: 텍스트 크롤링
await page.waitForSelector(".article p.large");
const text = await page.evaluate(() => {
const anchor = document.querySelector(".article p.large");
return anchor.innerHTML;
});
return text;
};
app.get("/gotoEtaV2", (req, res) => {
const url = "https://everytime.kr/409275/v/227352083";
(async () => {
const options = {
args: [
"--fast-start",
"--disable-web-security",
"--disable-features=IsolateOrigins",
"--disable-site-isolation-trials",
"--disable-extensions",
"--disable-setuid-sandbox",
"--no-sandbox",
],
ignoreHTTPSErrors: true,
headless: false,
ignoreDefaultArgs: ["--disable-extensions"],
};
try {
// FIXME: 초기설정
const browser = await puppeteer.launch(options);
const page = await browser.newPage();
const everytimeUrl = url;
await page.goto(everytimeUrl, [
"load",
"domcontentloaded",
"networkidle0",
]);
setIdPwV2(page);
// FIXME: 텍스트 / 사진 크롤링
const text = await getTextV2(page);
console.log(text);
// const img = await getImg(page);
// const profile = await getProfile(page);
// console.log(profile);
res.json({ text });
// FIXME: 브라우져 닫기
await browser.close();
} catch (error) {
console.log("Error " + error.toString());
res.send("오류발생1");
}
})();
});
app.listen(process.env.PORT || 3001, () => {
console.log("SERVER RUNNING ON PORT 3001");
});
pakage.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^14.2.0",
"express": "^4.17.2",
"nodemon": "^2.0.15",
"puppeteer": "^13.0.1"
},
"type": "module"
}
heroku.yml
build:
docker:
web: Dockerfile
run:
web: bundle exec puma -C config/puma.rb
# web: /bin/sh -c bundle exec puma -C config/puma.rb
2
Answers
i've solved that issue with this deploy way
just put those command on your vscode terminal
saurce https://www.youtube.com/watch?v=6l55lOyerZk
You appear to have copied the sample
config.yml
from Heroku’s documentation but not modified it for Node.js.The
run
section tells Heroku how to run your application by defining process types (e.g.web
) and commands to run for each one. Instead of usingbundle exec puma
, which might be appropriate for a Rails application, put in whatever command you use to start your production application.Based on your
package.json
, something like this would be more appropriate: