Docker 系列 - 05 - 入門 & Puppeteer 服務

jsliang發表於2022-03-14

一、前文回顧 & 前言

經過前文的講解,想必大家已經對 Docker 有比較深的印象了,那麼這篇文章我們將長話短說:

  • 如何將 Puppeteer 這種無頭瀏覽器塞到 Docker 中

二、Puppeteer 目錄結構

管理,我們的服務還是基於之前的 Node.js 服務改造,所以 jsliang 拿了自己寫的一個基礎 Node.js + TypeScript 的服務。

它的目錄結構如下:

docker-puppeteer

Docker-demo-26.jpg

啟動這個 Demo 只需要 2 步:

  • 安裝包:npm i
  • 啟動服務:npm run robot-test

等到每分鐘的第 0 秒的時候,終端操作開啟 Puppeteer,並將圖片存放到 src/source 上。

關鍵程式碼是:

src/index.ts
// ……程式碼省略
console.log('你好,已進入程式');
let time = 0;
await schedule.scheduleJob('0 * * * * *', async () => {
  const browser = process.env.NODE_ENV === 'production' ?
    // 正式環境需要開啟沙盒模式
    await puppeteer.launch({
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    }) :
    // 非正式環境則隨意
    await puppeteer.launch({
      headless: false, // 非無頭模式,
      devtools: true, // 除錯模式,可以在控制檯看到 console
    });
  
  // 建立新標籤頁並開啟
  const page = await browser.newPage();
  await page.goto('https://www.baidu.com/s?wd=jsliang');

  // 等待 5 秒載入
  await page.waitForTimeout(5 * 1000);

  // 獲取快照並儲存到本地
  await page.screenshot({
    path: `./src/source/baidu_${++time}.png`,
  });

  // 關閉視窗
  await browser.close();
});
// ……程式碼省略

感興趣的小夥伴可以停下來開啟倉庫,先看下 Demo,不感興趣的可以繼續往下看。

我們看下關鍵中的關鍵:

src/index.ts
const browser = process.env.NODE_ENV === 'production' ?
  // 正式環境需要開啟沙盒模式
  await puppeteer.launch({
    args: ['--no-sandbox', '--disable-setuid-sandbox'],
  }) :
  // 非正式環境則隨意
  await puppeteer.launch({
    headless: false, // 非無頭模式,
    devtools: true, // 除錯模式,可以在控制檯看到 console
  });

因為如果是通過 Docker 構建 Node.js 服務的話,我們是沒法正常啟動 Puppeteer 的,所以需要:

  1. 設定 Dockerfile
  2. 設定 launch 的姿勢

這裡我們的 package.json 程式碼:

package.json
"scripts": {
 "robot": "cross-env NODE_ENV=production ts-node ./src/index.ts robot",
 "robot-test": "cross-env NODE_ENV=test ts-node ./src/index.ts robot"
},

所以,我們設定到 launch 後,只需要在在正式環境執行 npm run robot,即可啟動沙盒模式。

三、編寫 Dockerfile

話不多說,我們直接編寫 Dockerfile:

Dockerfile
# 官方文件 https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-in-docker
# 基於 Alpine Linux 的最小 Docker 影像,具有完整的包索引,大小僅為 5 MB!
FROM alpine:edge

# 指定執行 CMD 的目錄,即先 cd 到該目錄上
WORKDIR /home/docker/we_render

# 安裝最新版 Chromium(89) 的包
RUN apk add --no-cache \
      chromium \
      nss \
      freetype \
      harfbuzz \
      ca-certificates \
      ttf-freefont \
      nodejs \
      yarn

# 跳過自動安裝 Chrome 包. 使用上面已經安裝的 Chrome
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

# Puppeteer v6.0.0 配套 Chromium 89
RUN yarn add puppeteer@6.0.0

# 拷貝宿主機的檔案到容器中的 we_render 目錄
COPY . /home/docker/we_render

# 通過 yarn 設定淘寶源和裝包,並清除快取
RUN yarn config set registry 'https://registry.npm.taobao.org' && \
    yarn global add pm2 && \
    yarn install && \
    yarn cache clean

# 宣告容器提供的服務埠
EXPOSE 9527

# 容器主程式的啟動命令
CMD ["yarn", "run", "robot"]

然後只需要按部就班建立映象和建立容器等操作即可。

四、啟動服務

注意:強烈建議先切換映象,否則下載內容會非常慢,之前我在公司操作還行,回來自己掛科學上網也整了好久(3000s)。

修改映象方法:03 - 入門 & 概念解疑

  • 建立映象(Image):docker image build ./ -t docker-node:1.0.0

Docker-demo-27.jpg

  • 建立容器(Container):docker container create -p 3333:80 docker-node:1.0.0
  • 啟動容器(Container):docker restart dd420fc4267ad3bdb9eadfdbf37d89e2592dbc9d030a501b96fe10b07ac565ff
  • 檢視容器(Container)執行情況:docker ps -a
  • 檢視容器(Container)的日誌:docker logs -f dd420fc4267a
  • 進入容器(Container):docker exec -it dd420fc4267a bash
  • 前往目錄:cd src/source
  • 檢視目錄內容:ls

可以看到,我們已經有幾張截圖了:

Docker-demo-28.jpg

使用前面學習的方法,將容器的內容拷貝出來,並檢視下:docker cp f5000c4a530b:/home/docker/we_render/src/source E:\MyWeb\all-for-one

Docker-demo-29.png

雖然不懂 ??? 是什麼鬼,但是好歹能正常運轉了!

那麼,我們將 Puppeteer 塞到 Docker 上就成功啦,剩下的只需要將時區和 Hosts 設定下就可以了,這裡就不一一贅述了。

這樣,我們的 Docker 之旅就先告一段落了,感興趣的小夥伴歡迎催更,後續的 本地編寫 Git 倉庫程式碼,然後 push 到 GitHub 後,走 CI/CD 並更新到伺服器…… 操作,只能等 jsliang 有時間了再進一步更新啦!

我是 jsliang,一個充滿探索欲,喜歡折騰,樂於擴充套件自己知識面的終身學習斜槓程式設計師,讓我們一起來折騰探索吧!


不折騰的前端,和鹹魚有什麼區別!

覺得文章不錯的小夥伴歡迎點贊/點 Star。

如果小夥伴需要聯絡 jsliang

個人聯絡方式存放在 Github 首頁,歡迎一起折騰~

爭取打造自己成為一個充滿探索欲,喜歡折騰,樂於擴充套件自己知識面的終身學習斜槓程式設計師。

jsliang 的文件庫由 樑峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可。<br/>基於 https://github.com/LiangJunrong/document-library 上的作品創作。<br/>本許可協議授權之外的使用許可權可以從 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 處獲得。

相關文章