[ Day 05 ] 用 Puppeteer 來做自動化機器人吧 (四) : Dockerize 篇


上篇 用 Puppeteer 來做自動化機器人吧 (三) : 應用篇 用 Puppeteer 實作了機器人自動排程貼文,今天想來談談 Puppeteer 如何 Dockerize,以便可以部署在不同環境上。

接下將分享如何建立 Dockerfile 以及幾項我當初實作時遇到的一些小雷。

一、建立 Dockerfile

第一步是要先下載 Docker,這邊就不多贅述。接下來在專案底下建立 Dockerfile,將下方程式碼複製貼上後儲存。

接下來要先 build image,指令為 docker build -t puppeteer-bot .

build 完後就可以 docker run -d --name puppeteer-bot-timeline puppeteer-bot:latest

我們可以透過 docker logs puppeteer-bot-timeline 查看 console.log 出來的內容 ( 如果有的話 )。

* 記得 headless 要設定為 true 才能運行唷。

FROM node:11-slim
# 下載 chromium 在 docker 運行時所需套件
RUN apt-get update && apt-get install -yq libgconf-2-4
RUN apt-get update && apt-get install -y wget --no-install-recommends \
    && 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-unstable \
      --no-install-recommends \
    && rm -rf /var/lib/apt/lists/* \
    && apt-get purge --auto-remove -y curl \
    && rm -rf /src/*.deb

ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 /usr/local/bin/dumb-init
RUN chmod +x /usr/local/bin/dumb-init
USER root
ENV TZ=Asia/Taipei # 轉換時區,非必要
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY . /app/
WORKDIR app
RUN npm install
EXPOSE 8084
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "main.js"]

踩雷點分享

接下來想跟大家分享當初在 Dockerize 遇到的一些狀況:

1. Puppeteer 安裝 Chromium 時會缺少一些套件

一開始想說 Dockerize 應該很容易,安裝 node 然後 npm install 就好了,但沒想到一直報錯說 Chromium 缺少套件。後來去 Puppeteer 的 issue 上查到原來安裝 Puppeteer 時會自動安裝 Chromium,但要在 Docker 上運行的相關套件並不會自動下載,後來就照著 Github 上的教學去安裝相關套件,後續才能運行。

2. Page Focus 問題

在開發時我是透過開啟一個 browser,然後持續開三個分頁來操作,希望能加快處理的速度。開發過程中我發現當 headless : false 時,他會同時開啟三個分頁,但只有被 focus 的 tab 有在運行接下來的 script,另外兩頁並沒有。因為我在運行完會被 tab close,所以接下來第二頁被 focus 後會再開始運行。

查了一下 issue,有查到一樣的問題,但在 headless: true 的時候,是會同時處理的,但目前還沒找到其他解法。

3. Page Crash 問題

上面有提到我在一個瀏覽器上操作三個分頁,放在 docker 上運行,一直遇到 Page Crash 問題,原先覺得是 memory 開不夠,但在 aws 上看 memory 使用狀況覺得好像還好。後來有在 issue 上查到原來要在 launch browser 時加上 --disable-dev-shm-usage

By default, Docker runs a container with a /dev/shm shared memory space 64MB.
This is typically too small for Chrome and will cause Chrome to crash when rendering large pages.
To fix, run the container with docker run --shm-size=1gb to increase the size of /dev/shm.
Since Chrome 65, this is no longer necessary.
Instead, launch the browser with the --disable-dev-shm-usage flag:
const browser = await puppeteer.launch({
args: ['--disable-dev-shm-usage']
});

4. 時區問題

這個問題跟 Puppeteer 比較無關,是跟上篇在實作 LINE 貼文串發文機器人相關。我在 docker 上運行時,將排程時間設定為 7:00,但實際去後台看會變成 15:00,但我很確定機器人是輸入 7:00 ( 畢竟是一個一個數字輸入 ),後來發現 LINE 貼文串後台會自動幫你轉時區(!),所以就要在 Dockerfile 指定 container 的時區,才不會被加 8 小時。

總結

今天分享了如何建立 Dockerfile,能夠在 Docker 運行 Puppeteer。也分享了四個遇到的問題,希望對大家有幫助。如果有任何建議,也歡迎指教及分享,謝謝!

參考資料

  1. Hosting Puppeteer in a Docker container
  2. 在自己建立的 Debian docker image 設定時區
  3. What is "Page crashed!" error?
#node.js #Puppeteer







你可能感興趣的文章

給每個Python專案一個乾淨獨立的環境

給每個Python專案一個乾淨獨立的環境

什麼是閉包 closure?

什麼是閉包 closure?

React Next.js and Material UI(MUI)

React Next.js and Material UI(MUI)






留言討論